WordPress-admin blijft laden na inloggen

Je logt netjes in, de admin-bovenbalk verschijnt, en daarna blijft de pagina rondjes draaien. In dit artikel leg ik uit waarom het eerste verzoek na een succesvolle login het meest fragiele moment in een WordPress-installatie is, welke mechanismen het laten vastlopen, en hoe je dit symptoom uit elkaar houdt met de problemen waar het meestal de schuld van krijgt.

Een login die slaagt en een dashboard dat nooit afrendert, zijn twee verschillende problemen verpakt in één symptoom. De cookie-uitwisseling werkte. De browser is geauthenticeerd. De HTML komt al binnen. En toch blijft de pagina half hangen, met de admin-sidebar in beeld en het hoofdpaneel op een spinner. Specifiek dat beeld, waarbij de request loopt maar nooit afrondt, is waar dit artikel over gaat. Het is niet hetzelfde als niet kunnen inloggen, en het is ook niet hetzelfde als een algemeen trage admin.

Wat "blijft laden na inloggen" precies is

Concreet: je vult je inloggegevens in op wp-login.php, WordPress schrijft de auth-cookies, de browser volgt de redirect naar wp-admin/, en de response begint binnen te komen. De bovenbalk is er. Het admin-menu links is er. Het hoofdpaneel toont een spinner, een leeg vlak of een halve widget-grid die niet verder komt. Open je DevTools, dan staat de request naar wp-admin/index.php nog steeds in de wachtstand, soms wel dertig seconden lang, en daarna eindigt hij óf in een timeout zonder duidelijke melding óf rendert het dashboard alsnog na een paar minuten.

De crux zit in het tijdsverloop. Het eerste admin-verzoek ná het inloggen is het trage. Refreshen, doorklikken naar een ander admin-scherm of vijf minuten later terugkomen voelt meestal gewoon. Die asymmetrie is precies de reden dat dit symptoom een eigen concept-artikel verdient.

Kom je überhaupt niet in een admin-scherm, dan zit je in geen toegang tot wp-admin zonder foutmelding. Voelt élke admin-klik traag, dus ook de tweede en derde, dan zit je in waarom de WordPress-admin traag is. Het artikel dat je nu leest behandelt specifiek die ene piek op de eerste klik na de login.

Hoe een wp-admin-request eigenlijk opstart

Bijna elke oorzaak achter een vastlopende post-login admin zit in de keten van hooks die WordPress afvuurt terwijl hij een admin-scherm in elkaar zet. Die keten is gedocumenteerd en de volgorde ligt vast: init, dan widgets_init, dan wp_loaded, dan admin_menu, dan admin_init, en dan de scherm-specifieke render. Elke actieve plugin krijgt op elk van die hooks de kans om code te draaien.

Twee dingen maken die keten zwaarder dan een vergelijkbaar front-end-verzoek. Ten eerste zit WordPress voor admin-URL's niet achter een page cache, dus elke klik gaat het volledige PHP-pad door zonder shortcut. Ten tweede zetten plugins het grootste deel van hun admin-code achter is_admin() en draaien ze die op admin_init, waardoor het post-login dashboard de eerste plek is waar een verse admin-sessie de hele admin-codebase van elke actieve plugin op één PHP-worker, in serie, moet uitvoeren. De documentatie van admin_init is daar duidelijk over: de hook draait óók op admin-ajax.php en admin-post.php, dus hij ligt op het hete pad van élke admin-actie.

Loopt die bootstrap binnen een paar honderd milliseconden af, dan merk je er niks van. Blokkeert er iets in de keten dertig seconden lang, dan staar je naar de spinner waar dit artikel over gaat.

Waarom juist dat eerste verzoek de zwakste plek is

De post-login dashboard-request is structureel het worst case van élke admin-request in de hele cyclus. Vijf dingen stapelen op die ene klik en elke volgende admin-klik betaalt voor minder ervan.

Koude caches. De opcode-cache heeft de admin-codebase van elke plugin nog niet gecompileerd. Object-cache-entries waar de admin-queries op leunen zijn nog leeg. Transients die remote API-responses bewaren (community events, update-checks, dashboard-feeds) zijn leeg of verlopen. De eerste admin-klik is degene die ze moet vullen.

WP-Cron die de achterstand inhaalt. WordPress draait wp-cron op page loads, niet via een echte cron-daemon (tenzij je dat zelf hebt geregeld). De officiële cron-documentatie zegt het zo: "WP-Cron does not run constantly as the system cron does; it is only triggered on page load." De eerste admin-klik na een rustige periode erft elke achterstallige geplande taak: een backup die zijn slot gemist heeft, update-checks, plugin-onderhoud, geplande posts. Die draaien allemaal op dezelfde PHP-worker die jouw dashboard probeert te serveren, in serie, voordat de response klaar is.

Initialisatie van Heartbeat en autosave. Zodra de dashboard-JavaScript opstart, begint de Heartbeat API te pollen op admin-ajax.php?action=heartbeat. De standaardtick is 15 seconden in de classic editor en 60 seconden op het dashboard, met AUTOSAVE_INTERVAL standaard op 60 seconden voor de autosaves van de editor. Op zichzelf vertraagt dat het renderen niet, maar als een plugin heartbeat_received heeft gehookt om er écht werk in te doen, dan landt de tweede klik (de eerste heartbeat-tick) midden in een nog niet uitgewerkte bootstrap en lopen de symptomen door elkaar.

Dashboard-widgets die remote data ophalen. De core-dashboard rendert de WordPress Events and News-widget, die WP_Community_Events::get_events() aanroept tegen https://api.wordpress.org/events/1.0/. Die request wordt 12 uur in een transient gecached, dus de meeste page loads zijn gratis. De eerste dashboard-load nadat die cache verloopt (of na een verse login op een rustige site) is degene die de round trip betaalt. Als api.wordpress.org traag of onbereikbaar is, dan stalt de widget je dashboard tot de HTTP-timeout afloopt.

Plugin-code op admin_init die maar eens per sessie draait. Plugins die license-checks, schemamigraties, "first-run after update"-routines of remote calls naar een vendor-API uitstellen, hangen die code vaak op admin_init met een transient als slot. De eerste admin-klik na een update krijgt de trage variant. De volgende klikken krijgen de gecachede.

Een site die alle vijf tegelijk raakt op dezelfde request kan bijna een minuut op de spinner blijven hangen om daarna gewoon door te lopen. Dat is de kenmerkende handtekening van blijven-laden-na-inloggen.

Veelvoorkomende oorzaken die dit symptoom geven

Niet elke site raakt elke oorzaak, maar de post-login bootstrap is zwaar genoeg dat één traag onderdeel meestal al genoeg is om hem vast te zetten.

Heartbeat- of autosave-overload door een vergeten editor-tab. Een teamlid heeft ergens nog een editor-tab openstaan in z'n browser. Die tab pingt nog steeds heartbeats. Op het moment dat jij inlogt, vechten jouw dashboard-request en zijn heartbeat-tick om dezelfde PHP-FPM worker pool. Op een kleine pool is dat genoeg om de post-login bootstrap in de wachtrij te duwen. Het artikel over PHP-workers in WordPress gaat dieper in op dat queue-mechanisme.

Langlopend plugin-werk op admin_init. Een plugin checkt op updates, haalt een license-status op, draait een schemamigratie of pingt een vendor-API bij elke admin-request zonder transient als rem. De eerste klik na het inloggen betaalt de volle prijs. Membership-, LMS-, backup- en beveiligingsplugins zijn meestal de boosdoeners. Een plugin die synchroon een externe API aanroept op admin_init kan de bootstrap stilzetten zo lang als die externe service nodig heeft om te antwoorden.

Een geblokkeerde REST API-call vanuit de blokkeneditor. Land je na de login niet op het dashboard maar in de post-editor, dan begint die meteen een stortvloed aan REST API-calls te vuren (autosave-probes, post locks, taxonomy-lookups, herbruikbare blokken). Een 403 op de REST API, een trage OPTIONS-preflight, of een beveiligingsplugin die wp-json/ afknijpt, geeft hetzelfde zichtbare symptoom: de editor mount nooit door.

Een dashboard-widget die trage remote data ophaalt. wp_dashboard_primary() laadt RSS-feeds van wordpress.org/news en planet.wordpress.org, en een third-party widget van een marketing- of analytics-plugin kan synchroon naar een externe URL praten zonder zinnige timeout. De index.php-request van het dashboard wacht op de traagste widget op het scherm.

WP-Cron die op de eerste admin-klik z'n achterstand inhaalt. Op een site met weinig verkeer waar uren niemand is geweest, is de post-login dashboard-klik de eerste request die WordPress weer wakker maakt, dus dweilt wp-cron in één keer de hele backlog van due events af op die ene request. Een backup die om 03:00 had moeten draaien, een update-check van 04:00 en een dagelijkse plugin-housekeeping draaien achter elkaar voordat de response wordt afgesloten. De oplossing is hier zelden "maak het dashboard sneller"; het is om interne wp-cron uit te zetten met define( 'DISABLE_WP_CRON', true ) en wp-cron.php elke minuut vanuit een echte system cron aan te trappen, wat de wp-config-referentie gewoon documenteert.

Praktische implicaties voor het herkennen van het symptoom

De vorm van de stilstand vertelt je welk van de vijf mechanismen aan het werk is.

  • Eerste admin-klik na inloggen is traag, alle volgende klikken zijn snel. Klassiek bootstrap-probleem. Koude caches, WP-Cron die inhaalt, of plugin-code die maar eens per sessie op admin_init draait. Probeer een minuut later opnieuw in te loggen om te zien of die tweede login óók traag is; is dat niet zo, dan ligt het niet aan cache-expiratie.
  • Dashboard hangt alleen wanneer andere editors in een ander tabblad bezig zijn. Heartbeat-verkeer en jouw bootstrap vechten om dezelfde PHP-workers. Of de pool is te klein voor het team, of iets laat de heartbeat-hook meer doen dan zou moeten.
  • Hangt alleen op één specifiek plugin-scherm. Die plugin doet synchroon werk op zijn admin-scherm-render en niet op het dashboard. De fix is óf vragen aan de plugin-auteur wat er veranderd is, óf dat ene scherm profileren met Query Monitor op een staging-kopie.
  • Hangt alleen op het dashboard, snel op elk ander admin-scherm. Een dashboard-widget haalt remote data op. Zet de WordPress Events and News-widget en eventuele third-party widgets één voor één uit om de boosdoener te vinden.
  • Hangt soms wel, soms niet. WP-Cron die inhaalt. Zet interne wp-cron uit en draai hem vanuit een system cron, dan haal je de variabiliteit eruit.

Wat blijven-laden-na-inloggen níet is

Deze sectie voorkomt het meeste verspilde zoekwerk. Het symptoom is specifiek genoeg dat er een hoop aangrenzende problemen zijn die de schuld krijgen zonder hetzelfde beeld te geven.

  • Het is geen wachtwoord- of login-probleem. De login is al gelukt. De auth-cookies zijn geschreven, de redirect is gevolgd, en de admin-URL antwoordt met 200 OK. Weigert het formulier je inloggegevens of stuiter je terug naar wp-login.php zonder dat je wp-admin/ ooit echt opent, dan zit je in een ander artikel: begin bij waarom je niet kunt inloggen in WordPress.
  • Het is geen cookie-probleem. Cookies werken, anders zou de admin-bovenbalk nooit verschijnen en zou je je gebruikersnaam niet rechtsboven zien staan. Het symptoom "cookies zijn geblokkeerd" ziet er compleet anders uit: WordPress weigert dan de login-submit met een expliciete melding voordat het dashboard überhaupt laadt. Dat geval staat in cookies zijn geblokkeerd of worden niet ondersteund in WordPress.
  • Het is niet hetzelfde als een algemeen trage admin. Een trage admin is de cumulatieve kostenpost van élke admin-klik die zwaarder is dan de vergelijkbare front-end-klik: te veel autoload, te veel plugins die op is_admin() draaien, een editor-team dat de heartbeat zwaar belast, trage database-queries op elke list table. Dat is een continue, lineair voelende traagheid die ook op de tweede en derde klik blijft, en dat is een eigen concept-artikel: waarom de WordPress-admin traag is. De post-login bootstrap is juist die eenmalige piek op de eerste klik; voelt elke klik even traag, dan zit je in dat andere artikel.
  • Het is geen server-down-probleem. De inlogpagina laadde voor je. De server accepteerde de POST, controleerde je wachtwoord, schreef cookies en begon het dashboard te serveren. Was de server écht down, dan had je een 502 Bad Gateway of 503 Service Unavailable van de voordeur gekregen. Het feit dat de spinner überhaupt bestaat, betekent dat PHP draait, dat de database bereikbaar is, en dat WordPress aan het bootstrappen is. De stilstand zit binnen die bootstrap, niet ervoor.
  • Het is geen redirect-loop. Een redirect-loop eindigt met ERR_TOO_MANY_REDIRECTS in de browser en komt nooit toe aan een halfgeladen dashboard. Dat symptoom hoort bij WordPress login redirect loop.

Waar je nu heen moet

Wil je de bredere kaart van élk login-symptoom en waar het naartoe wijst, dan is het umbrella-artikel waarom je niet kunt inloggen in WordPress. Rendert het dashboard helemaal niks (geen bovenbalk, geen menu, alleen een blanco of stuiterend scherm), dan is het juiste startpunt geen toegang tot wp-admin zonder foutmelding. Voelt élke admin-klik traag en niet alleen de eerste, dan dekt waarom de WordPress-admin traag is het cumulatieve patroon. En als de bootstrap vastloopt zodra andere admins tegelijk aan het werk zijn, dan legt het PHP-workers-artikel uit waarom admin-requests de pool als eerste verzadigen.

Klaar met terugkerende traagheid?

Traagheid komt vaak terug na snelle fixes. Professioneel onderhoud houdt updates, caching en limieten consequent op orde.

Bekijk WordPress onderhoud

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.