Admin-ajax.php: de verborgen performance drain

Ontdek waarom admin-ajax.php je WordPress-site vertraagt, hoe je de veroorzakers opspoort en welke oplossingen écht werken voor betere performance.

24 april 20267 min leestijdDoor We Develop Communication

Je server staat in brand, je TTFB schiet omhoog en je ziet in de logs één bestand steeds terugkomen: admin-ajax.php. Dit onschuldig ogende bestand is een van de meest onderschatte performance drains in WordPress. Het is geen bug, geen plugin, maar een kerncomponent die door jarenlang legacy-gebruik veranderd is in een bottleneck die veel sites langzaam nekt.

In dit artikel lees je hoe admin-ajax.php werkt, waarom het je site zoveel CPU en database-resources kost, en wat je concreet kunt doen om het weer onder controle te krijgen.

Wat is admin-ajax.php?

Admin-ajax.php is sinds WordPress 2.8 het centrale eindpunt voor AJAX-verzoeken. Oorspronkelijk bedoeld voor het admin-gedeelte, groeide het uit tot een universeel endpoint voor alle asynchrone requests, ook op de front-end.

Elke keer dat een plugin of thema een AJAX-call doet, stuurt de browser een POST-request naar /wp-admin/admin-ajax.php met een action-parameter. WordPress bootstrapt vervolgens volledig en koppelt die action aan een PHP-callback via de hooks wp_ajax_{action} of wp_ajax_nopriv_{action}.

Dat klinkt elegant, maar de truc zit in dat woord "bootstrapt". Bij elke request laadt WordPress de complete core, alle actieve plugins en je hele thema, zelfs als de callback maar drie regels code uitvoert.

Waarom admin-ajax.php je site afremt

Het probleem is niet de code zelf, maar het volume en de context waarin het draait. Een paar factoren die samen een perfecte storm vormen.

Volledige WordPress-bootstrap per request

Elke aanroep naar admin-ajax.php is in feite een mini-WordPress-pageload. Er worden queries uitgevoerd op wp_options, alle plugins worden geladen, alle hooks worden geregistreerd. Als je autoloaded options niet op orde zijn, voel je dat hier direct.

Geen page caching

Admin-ajax.php wordt door elke serieuze caching-oplossing genegeerd. Logisch, want het retourneert dynamische data. Maar dat betekent ook dat elke request je PHP-workers en database bezighoudt. Zie ook onze uitleg over full page caching voor de context.

Heartbeat API

De WordPress Heartbeat API pingt standaard elke 15 seconden naar admin-ajax.php als je in de admin zit, en elke 60 seconden op de front-end binnen de editor. Op drukke redactiesites levert dat duizenden requests per uur op, puur voor autosave-checks en lockscreens.

Plugins die alles via AJAX doen

Veel populaire plugins (formulieren, add-to-cart, filters, live search) sturen al hun verkeer via admin-ajax.php. Bij WooCommerce-sites is wc_ajax_add_to_cart vaak de meest aangeroepen action, gevolgd door wc-ajax-get-refreshed-fragments, en die laatste kan je server serieus pijn doen.

Admin-ajax.php in de praktijk herkennen

Voordat je iets oplost, moet je meten. Symptomen van admin-ajax.php-problemen zijn:

  • Pieken in CPU-gebruik zonder duidelijke verkeerspieken
  • Hoge TTFB op willekeurige momenten
  • Trage admin-omgeving, vooral bij meerdere ingelogde gebruikers
  • PHP-FPM workers die volraken (zie PHP-FPM tuning)

Meten met serverlogs

Je NGINX- of Apache-access log is de eerste plek om te kijken. Filter op requests naar admin-ajax.php en tel het volume:

grep "admin-ajax.php" access.log | wc -l
grep "admin-ajax.php" access.log | awk '{print $7}' | sort | uniq -c | sort -rn

Dat geeft je een globaal beeld. Voor de action-parameter moet je naar de POST-body kijken, want die staat niet in de URL.

Query Monitor

Installeer Query Monitor en kijk bij een AJAX-request welke queries en hooks er draaien. Vaak zie je dat één plugin verantwoordelijk is voor het leeuwendeel van de database-hits. Meer over deze aanpak lees je in debugging van trage plugins.

Browser DevTools

Open de Network-tab en filter op admin-ajax.php. Klik op een request en bekijk de Payload: de action-parameter vertelt je welke functie wordt aangeroepen. Dat is je smoking gun.

De heartbeat temmen

Als de Heartbeat API de grootste veroorzaker is, kun je die eenvoudig aanpassen. Drie opties.

Interval verhogen

add_filter('heartbeat_settings', function($settings) {
    $settings['interval'] = 60;
    return $settings;
});

Daarmee gaat de admin-heartbeat van 15 naar 60 seconden. Op een site met tien ingelogde redacteuren scheelt dat 75% van het heartbeat-verkeer.

Locatiegewijs uitschakelen

add_action('init', function() {
    if (!is_admin()) {
        wp_deregister_script('heartbeat');
    }
}, 1);

Hiermee schakel je de heartbeat volledig uit op de front-end. Let op: autosave in Gutenberg heeft de heartbeat nodig, dus laat 'm op admin-pagina's actief.

Plugin-route

Wil je niet zelf coderen, dan biedt Heartbeat Control een UI voor dezelfde instellingen. Eén plugin meer, maar wel laagdrempelig.

WooCommerce-fragments aanpakken

Als je WooCommerce draait, is wc-ajax-get-refreshed-fragments vrijwel gegarandeerd je grootste boosdoener. Elke pagelaad haalt de winkelmand-fragmenten op, ook als er niets in de mand zit.

De oplossing: laad fragmenten alleen wanneer de mand daadwerkelijk iets bevat. Er zijn plugins zoals Disable Cart Fragments, maar je kunt het ook zelf doen:

add_action('wp_enqueue_scripts', function() {
    if (is_null(WC()->cart) || WC()->cart->is_empty()) {
        wp_dequeue_script('wc-cart-fragments');
    }
}, 11);

Dit bespaart op productpagina's en blogposts al snel honderden milliseconden TTFB voor bezoekers zonder winkelmand.

Van admin-ajax.php naar REST API

Voor nieuwe functionaliteit is de WordPress REST API bijna altijd de betere keuze. Die is lichter, cachebaar via HTTP-headers en beter gestructureerd. We schreven er een volledig artikel over: REST API performance in WordPress optimaliseren.

Een concreet verschil: een REST-endpoint kun je via NGINX of een reverse proxy cachen op URL-niveau. Admin-ajax.php niet, want alles gaat via POST naar dezelfde URL, de action-parameter zit in de body.

Bouw je zelf een plugin of custom integratie? Registreer een REST-route in plaats van een AJAX-action:

add_action('rest_api_init', function() {
    register_rest_route('mijnplugin/v1', '/data', [
        'methods'  => 'GET',
        'callback' => 'mijn_data_handler',
        'permission_callback' => '__return_true',
    ]);
});

Object caching als vangnet

Omdat admin-ajax.php niet gecached kan worden op HTTP-niveau, moet je de impact binnen PHP opvangen. Object caching met Redis is hiervoor de belangrijkste tool.

Veel AJAX-callbacks doen dezelfde queries telkens opnieuw: opties ophalen, user meta uitlezen, taxonomieën checken. Met een persistente object cache (Redis of Memcached) hoeven die queries maar één keer uitgevoerd te worden per cache-cyclus.

Voor callbacks die zware berekeningen doen, kun je de resultaten zelf cachen met transients:

function mijn_ajax_callback() {
    $cache_key = 'mijn_ajax_' . md5(serialize($_POST));
    $data = get_transient($cache_key);

    if (false === $data) {
        $data = dure_berekening();
        set_transient($cache_key, $data, 5 * MINUTE_IN_SECONDS);
    }

    wp_send_json_success($data);
}

Specifieke acties blokkeren op serverniveau

Sommige AJAX-endpoints worden misbruikt door bots of scrapers. Denk aan login-brute-force via wp-ajax-login of spam via contactformulieren. Op NGINX-niveau kun je die requests weren voordat PHP überhaupt aangeslingerd wordt:

location = /wp-admin/admin-ajax.php {
    if ($http_referer !~* "jouwdomein.nl") {
        return 403;
    }
    include fastcgi_params;
    fastcgi_pass php-fpm;
}

Let op: referer-filtering is geen waterdichte beveiliging, maar het schakelt het gros van het geautomatiseerde verkeer uit. Voor echte hardening kijk je beter naar rate limiting en onze gids over security hardening.

Monitoring: houd het onder controle

Het grootste probleem met admin-ajax.php is dat het onzichtbaar wegkruipt in je stats. Google Analytics rapporteert er niet over, de meeste APM-tools tellen het niet mee als pageview.

Zet daarom structurele monitoring op:

  • Logging van action-parameters, schrijf bij elke AJAX-call de action en executietijd weg
  • APM-tooling, New Relic of Blackfire.io laten je per action zien hoeveel tijd er verloren gaat
  • Slow query log, MySQL's slow query log verraadt welke AJAX-callbacks dure queries doen
  • PHP-FPM slowlog, zet request_slowlog_timeout aan om calls boven een bepaalde drempel te loggen

Meer over dit soort monitoring lees je in WordPress logs analyseren als een pro en performance bottlenecks herkennen.

Wanneer is admin-ajax.php nog de juiste keuze?

Niet alles hoeft weg. Admin-ajax.php is nog steeds prima voor:

  • Legacy plugins die je niet kunt aanpassen
  • Admin-only functionaliteit met lage frequentie
  • Simpele nonce-gevalideerde acties waar de REST API overhead overkill is
  • Integraties met oudere JavaScript-libraries die geen REST-client ondersteunen

Waar het misgaat, is high-frequency front-end gebruik. Live search, infinite scroll, cart fragments, dat soort zaken hoort bij de REST API of zelfs bij een headless architectuur.

Veelgestelde vragen

Wat is admin-ajax.php precies?

Admin-ajax.php is het centrale eindpunt in WordPress voor AJAX-verzoeken vanuit zowel de front-end als het admin-gedeelte. Plugins en thema's gebruiken het om data op te halen of te verwerken zonder de pagina te herladen.

Waarom is admin-ajax.php zo traag?

Elke aanroep laadt de volledige WordPress-core, inclusief plugins en thema. Dat betekent een complete bootstrap per request, vaak zonder caching. Bij veel bezoekers of heartbeat-activiteit stapelt dat snel op.

Kan ik admin-ajax.php uitschakelen?

Nee, uitschakelen breekt veel functionaliteit. Wel kun je specifieke acties blokkeren, de heartbeat tunen of AJAX-calls vervangen door de REST API voor betere performance.

Hoe zie ik welke plugin admin-ajax.php belast?

Gebruik Query Monitor, de Network-tab in DevTools of serverlogs om de action-parameter te inspecteren. Die parameter verraadt welke plugin of functie de request triggert.

Is de REST API een betere keuze dan admin-ajax.php?

Vaak wel. De REST API is lichter, cachebaar en gestructureerd. Voor nieuwe functionaliteit is het meestal de betere keuze, al blijft admin-ajax.php relevant voor legacy plugins.

Tot slot

Admin-ajax.php is niet de vijand, het is een kerncomponent van WordPress die gewoon veel aandacht vraagt. Door de heartbeat te tunen, cart fragments te beperken, waar mogelijk over te stappen op de REST API en object caching serieus te nemen, haal je het merendeel van de performance-pijn weg.

Meet altijd eerst. Pas wanneer je weet welke action je server belast, kun je gericht ingrijpen. En zodra je die analyse onder de knie hebt, wordt admin-ajax.php van een verborgen drain een voorspelbare, beheersbare factor in je WordPress-stack.

Veelgestelde vragen

Klaar om digitaal te groeien?

Wij helpen Nederlandse bedrijven met webtechnologie en SEO-strategieën die écht werken. Neem vrijblijvend contact op.