Waarom de WordPress-admin traag is

Een WordPress-dashboard dat hapert terwijl de publieke site razendsnel blijft, is een van de meest voorkomende WordPress-klachten. De oorzaak is structureel, geen bug. De admin draait een fundamenteel ander soort verzoek dan de voorkant, en bijna elke optimalisatie die bezoekers helpt, doet niets voor de admin. Dit artikel legt uit waarom.

Een verzoek aan wp-admin en een verzoek aan de voorkant van dezelfde WordPress-site zijn niet hetzelfde soort werk. De voorkant is één van een paar duizend identieke pagina's die uit de cache geserveerd kan worden zonder dat PHP überhaupt aan zet komt. De admin is een persoonlijke, per-gebruiker, niet-cachebare interface die per request een zwaarder plugin-pad draait, op de achtergrond de server staat te pollen en méér uit de database trekt dan de publieke pagina. Dit artikel gaat over waarom die verschillen er zijn en welke symptomen ze opleveren. Is de voorkant ook traag, dan loopt het overkoepelende artikel over een trage WordPress-site door wat daar speelt.

Waarom een wp-admin verzoek zwaarder is dan een front-endverzoek

Vijf dingen maken elk admin-verzoek duurder dan het vergelijkbare front-end-verzoek. Stuk voor stuk by design.

Geen page cache. Een full-page cache (Varnish, nginx fastcgi_cache, LSCache, een WP Rocket disk cache, een CDN edge) levert identieke HTML aan identieke bezoekers zonder WordPress te booten. De admin kan zo niet werken: elk scherm is gepersonaliseerd voor de ingelogde gebruiker, opgesierd met security nonces met een korte houdbaarheid, en gevuld met data die de gebruiker net heeft bewerkt. Er is niets te delen tussen twee admin-sessies, dus er is niets te cachen (zie WordPress-cache werkt niet voor meer over de logged-in bypass). Elke admin-klik gaat de lange route: nginx geeft het verzoek aan PHP-FPM, een worker boot WordPress, plugins laden, queries draaien, HTML wordt opgebouwd, het antwoord komt terug. Hetzelfde pad dat een front-endbezoeker alleen op een cache miss aflegt, is het enige pad dat de admin ooit aflegt.

Een zwaarder plugin-codepad. De meeste plugins zetten het leeuwendeel van hun werk achter is_admin(), dat true teruggeeft binnen wp-admin en op admin-ajax.php. Settings-schermen, metaboxen, dashboard widgets, de extra kolommen in de Berichten- of Bestellingen-lijst, de sidebar-panels van de editor, de bulk-edit UI, upgrade-routines: niks daarvan draait op een publieke front-end-aanvraag. In de admin draait het allemaal bij elke pagina-load. Een site die op de voorkant twaalf plugin-bestanden per request aanraakt, kan er in admin makkelijk zestig aanraken.

De Heartbeat API. WordPress heeft een ingebouwd JavaScript polling-systeem, [de Heartbeat API](https://developer.wordpress.org/plugins/javascript/heartbeat-api/), dat vanuit elke openstaande admin-tab POST-verzoeken naar admin-ajax.php?action=heartbeat blijft sturen. De default tick is 15 seconden in de post-editor (zodat autosave en post locking werken) en 60 seconden op het dashboard. Elke tick is een volwaardig PHP-verzoek dat WordPress laadt en alles draait wat plugins aan de heartbeat_received filter hebben gehangen. Eén openstaande editor-tab levert vier requests per minuut op. Een team van vijf met de hele dag editor-tabs open, levert ongeveer 1.200 admin-requests per uur op zonder dat er ook maar iets gebeurt.

Autoload-bloat in wp_options. Elk WordPress-verzoek, voorkant of admin, roept wp_load_alloptions() aan, dat alle rijen uit wp_options ophaalt waarvan de autoload-kolom aan staat. Op een schone install is dat een paar honderd KB. Op een site die in de loop der jaren tientallen plugins heeft gezien komen en gaan, kunnen achtergebleven settings, license keys, transient-rommel en geserialiseerde arrays autoload zo de megabytes in duwen. WordPress 6.6 voegde een Site Health-check toe die autoload boven de 800 KB als kritiek probleem aanmerkt en zette een default cap van 150 KB per losse optie. De voorkant verstopt autoload-bloat achter de page cache, dus daar kost het bezoekers vrijwel nooit iets. De admin betaalt het bij elke klik.

Block editor en autosave XHRs. Een post openen in de block editor schiet op de achtergrond een hele stroom REST API-verzoeken af: autosave elke minuut, post lock-heartbeats, fetches voor reusable blocks, taxonomy- en user-lookups voor de sidebar, media library-queries zodra de inserter opent, REST API permission checks. Stuk voor stuk echte PHP-verzoeken die door PHP-FPM gaan, WordPress draaien, de database raken en weer terugkomen. De gebruiker ziet maar één editor-scherm, maar de server staat tientallen requests voor die ene tab te verwerken.

Waarom WordPress de admin zo ontwerpt

De admin ruilt prestaties in voor correctheid. Elk van die vijf dingen heeft een reden die zwaarder weegt dan adminsnelheid.

Een page cache kan een gepersonaliseerde, security-gevoelige interface niet serveren zonder data tussen gebruikers te lekken, dus de admin doet er bewust niet aan mee. Plugins gaten hun functionaliteit achter is_admin() zodat de voorkant snel blijft voor bezoekers, en dat is precies de juiste keuze. De Heartbeat API bestaat omdat twee editors die over dezelfde post heen werken een veel ergere fout is dan een traag dashboard. Autoload bestaat omdat één rij uit wp_options lezen per losse optie-aanroep desastreus zou zijn voor een site die honderden get_option()-calls per request doet. En het REST-verkeer van de block editor is precies wat Gutenberg laat aanvoelen als een echte applicatie in plaats van een formuliertje.

De rekening van die keuzes komt op de admin terecht omdat de admin de juiste plek is om die rekening neer te leggen. Een traag dashboard frustreert een handvol redacteuren. Een trage voorkant verliest klanten.

Wat dit praktisch betekent voor het diagnosticeren van een trage admin

De vorm van de traagheid vertelt je welke van de vijf mechanismen dominant is. Een paar patronen zie je vaak genoeg om ze meteen te herkennen.

  • Traag op elk admin-scherm, elke keer. Het PHP-pad zelf is zwaar. Of de autoload-rij is te groot (check Site Health), of de actieve pluginstack doet te veel in admin, of de database is traag op de queries die de admin draait. Het artikel over een trage database gaat in op de databasekant.
  • Alleen traag in de editor, dashboard prima. Het XHR-verkeer van de block editor is het gewicht. Open de network tab in je browser terwijl je in de editor zit. Zie je daar nog tien seconden na het laden een stroom REST API-calls doorgaan, dan weet je waar je voor betaalt.
  • Admin traag bij WooCommerce-werk, prima daarbuiten. Een WooCommerce-shop met duizenden bestellingen draait zware joins en meta-lookups op de orderlijst, het dashboard widget en de reports-pagina. Dat zijn de queries die in de admin opduiken en op de voorkant niet.
  • Traag zodra meerdere admins tegelijk zijn ingelogd. Heartbeat-verkeer plus admin-requests verzadigen de PHP worker pool. De admin is by far de makkelijkste manier om workers uit te putten, want elk admin-verzoek is niet-cachebaar, langer dan een front-end-verzoek en draait gelijktijdig met dat van andere editors.
  • Pas traag sinds een plugin-update. Een plugin is iets duurs gaan doen in is_admin()-modus dat hij eerder niet deed. Zet hem uit, kijk of de admin opveert en vraag dan de plugin-auteur wat er veranderd is.
  • Eerste klik traag, daarna snel. Cold start van de opcode cache. PHP heeft WordPress en de actieve plugins op het eerste verzoek opnieuw gecompileerd en daarna de bytecode gecached. Op een site met weinig verkeer kunnen opcache-entries verlopen voordat de volgende admin-klik komt. Het artikel over hoge TTFB gaat in op de opcache-kant.

Wil je daadwerkelijk zien welke queries op een bepaald admin-scherm draaien, installeer dan Query Monitor op een staging-kopie van de site. Het voegt een paneel toe in de admin toolbar dat elke databasequery, elke HTTP API-call, elke fired hook en de verantwoordelijke plugin of theme laat zien. Op een admin-scherm dat traag aanvoelt, wijst het paneel meestal binnen dertig seconden de oorzaak aan.

Wat een trage WordPress-admin niet is

De meeste tijd die je kwijt bent aan het diagnosticeren van een trage admin gaat zitten in het uitsluiten van dingen die op de oorzaak lijken maar het niet zijn. Dit zijn de verwarringen die de meeste uren kosten.

  • Niet hetzelfde als een trage voorkant. De voorkant en de admin zijn verschillende soorten verzoeken met verschillende knelpunten. Een site kan tegelijk een LCP van 1,2 seconden op de publieke homepage hebben en een admin-klik die er 4 seconden over doet, en de fixes overlappen niet. Caching, CDN's, image-optimalisatie, font preloading, CSS deferral: dat zijn allemaal dingen voor de voorkant en die doen vrijwel niets voor de admin. Voelen ze allebei traag, behandel het dan als twee aparte problemen en begin met de voorkant, want dat is degene die bezoekers zien. Het overkoepelende artikel over een trage WordPress-site gaat over de voorkant.
  • Niet puur een hosting-tier-probleem. Goedkope shared hosting maakt trage admins inderdaad erger, maar dezelfde site naar een groter pakket verhuizen lost het lang niet altijd op. De admin is op elk pakket per request zwaarder dan de voorkant. Een site met een autoload-rij van 2 MB, een Heartbeat-zwaar editorteam en een WooCommerce orders-tabel met magere indexes voelt ook op managed hosting traag. Hosting is een multiplier, geen oorzaak.
  • Geen thema-probleem. Thema's draaien in admin nauwelijks. De functions.php van een thema laadt wel, maar de templates niet, de front-end scripts worden niet enqueued en de CSS wordt niet geparsed. Van thema wisselen om een trage admin te fixen, doet vrijwel nooit iets. De plugins die hun zware code achter is_admin() hebben gezet, draaien na de themewissel gewoon door.
  • Niet hetzelfde als een hoge TTFB op de publieke site. TTFB op de voorkant meet één gecachet of ongecachet pagina-antwoord. Admin-traagheid is meestal cumulatief: veel queries, veel hooks, veel kleine XHRs, geen cache die er ook maar iets van opvangt. De diagnose voor een hoge front-end-TTFB vangt zelden waar de admin écht traag van wordt, want de admin betaalt een andere rekening.
  • Geen kwestie van het aantal plugins. "Te veel plugins" is de verkeerde eenheid. Eén plugin die op het dashboard widget een SELECT * over 200.000 orderrijen draait, doet meer pijn dan dertig plugins die zichzelf netjes gaten. Plugins tellen is een proxy die vaak genoeg klopt om goed te voelen en vaak genoeg faalt om je op het verkeerde been te zetten. Profilen wat elke plugin in admin daadwerkelijk doet, dat is de juiste aanpak.

Waar je verder kunt kijken

Is de publieke site ook traag, dan loopt het overkoepelende artikel over een trage WordPress-site door hoe je de juiste laag isoleert. Lijken de queries in admin het knelpunt, dan dekt het artikel over een trage database wat een WordPress-database traag maakt en hoe je naar indexes, autoload en N+1-patronen moet kijken. Zakt de admin pas in zodra meerdere redacteuren tegelijk werken, dan legt het artikel over PHP workers uit waarom admin-requests de pool als eerste verzadigen. Klimt het CPU-gebruik tegelijk mee, dan dekt het artikel over hoog CPU-gebruik de samenhangende signalen.

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.