...

NGINX Cache Purge op de juiste manier gebruiken: praktische handleiding voor het snel en veilig ongeldig maken van de cache

Ik laat je zien hoe je de nginx-cache doelgericht leegmaken, zonder bezoekers te confronteren met verouderde antwoorden of veiligheidsrisico’s te lopen. Met duidelijke purge-strategieën, schone cache-sleutels en een beveiligde automatisering bouw ik een Werkstroom die WordPress en PHP-FPM snel en up-to-date houdt.

Centrale punten

  • Cache-sleutels Goed plannen: host, URI, headers en noodzakelijke cookies
  • Zuiveringsstrategieën combineren: aflooptermijnen, specifieke sleutels, gecontroleerde 'Purge All'
  • Beveiliging voorkeur: interne IP-adressen, authenticatie, logboekregistratie, geen open eindpunten
  • Automatisering voordelen: WordPress-hooks en deploy-triggers voor purges
  • Controle Activeren: X-FastCGI-cache, logbestanden, cachegroottes

NGINX-caching begrijpen: de basis voor zinvol purging

Voordat ik ga purgen, begrijp ik hoe NGINX opslaat. NGINX bedient HTTP-backends via een proxycache en dynamische PHP-antwoorden via een FastCGI-cache; daarnaast bestaan er varianten zoals uWSGI of SCGI voor speciale opstellingen, die ik hier slechts kort aanstip. In typische WordPress- of PHP-stacks zorgt vooral de FastCGI-cache het grootste effect, omdat het kant-en-klare HTML-pagina’s vanuit PHP-FPM naar het bestandssysteem schrijft en deze bij de volgende oproep direct weergeeft. Dit ontlast de CPU en de database en verkort de responstijden, zolang de inhoud actueel is. Juist op dit punt bepaalt slim ‘purging’ of gebruikers actuele antwoorden krijgen of verouderde pagina’s te zien krijgen.

Cache-sleutels: de sleutel tot doelgericht opschonen

Elke treffer is gebaseerd op een Cache-sleutel, die meestal bestaat uit de host, de request-URI, relevante headers en een minimum aan cookie-gegevens. Ik stel de sleutel zo samen dat deze alleen rekening houdt met verschillen die de HTML-uitvoer daadwerkelijk wijzigen; anders versnipper ik de cache onnodig. Met Vary-headers, taal of apparaatklassen ga ik zuinig om en controleer ik met testverzoeken of de gewenste variatie echt nodig is. Een consistente sleutel maakt het later mogelijk om precies die objecten te verwijderen die door een wijziging worden beïnvloed, in plaats van grote mappen te wissen. Schone sleutels besparen I/O, houden het hitpercentage hoog en vergemakkelijken Zuiveren-Er is een enorme vraag.

Cache-key-ontwerp in de praktijk: normalisatie en reductie

In de praktijk normaliseer ik de key consequent: overbodige query-parameters worden verwijderd, slechts enkele whitelist-parameters blijven behouden, en cookies komen uitsluitend in de key terecht als ze de HTML-uitvoer zichtbaar wijzigen. Zo voorkom ik dat trackingparameters zoals utm_* of fbclid duizenden varianten van dezelfde pagina genereren.

# Cachezone en header
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=FCGI:256m inactive=60m max_size=10g;
map $http_cookie $no_cache {
  default 0;
  ~*wordpress_logged_in 1;
  ~*comment_author 1;
  ~*woocommerce_items_in_cart 1;
}
# Alleen GET/HEAD cachen, POST nooit
map $request_method $cache_method_ok { default 0; GET 1; HEAD 1; }
# Query-string op de witte lijst zetten: bijv. paginering en zoeken
map $arg_page $qs_page { "" ""; default "page=$arg_page"; }
map $arg_s    $qs_s    { "" ""; default "s=$arg_s"; }
# Lege onderdelen onderdrukken en samenvoegen
map "$qs_page$qs_s" $qs {
  "" "";
  default "?$qs_page$qs_s";
}
# Pad zonder queryreeks
map $request_uri $path_noargs { ~^([^?]+) $1; }
# Consistente cache-sleutel
set $my_cache_key "$scheme$host$path_noargs$qs";

server {
  # ...
  location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php-fpm.sock;

    # Cache-instellingen
    fastcgi_cache FCGI;
    fastcgi_cache_key $my_cache_key;
    fastcgi_cache_methods     GET HEAD;
    fastcgi_no_cache $no_cache;
    fastcgi_cache_bypass $no_cache;
    add_header X-FastCGI-Cache $upstream_cache_status always;
  }
}

Ik houd de Geen cache-Regel: aangemelde gebruikers, winkelmandjes en auteurs van reacties omzeilen de cache; anonieme lezers blijven hiervan profiteren. Voor apparaatklassen of talen maak ik een bewuste keuze: als CSS/JS al responsief werkt, zie ik af van een variatie in de sleutel en verhoog ik zo het aantal treffers.

Waarom gericht purgen van cruciaal belang is

De inhoud verandert voortdurend: nieuwe berichten, aangepaste menu’s, gewijzigde startpagina’s of sjabloonwijzigingen die de HTML-structuren aanpassen, en juist op dat moment wil ik bepalen wat de cache weergeeft. Zonder gericht leegmaken serveert NGINX oude bestanden totdat ze verlopen, wat in het ergste geval dagen kan duren en voor lezers onjuiste informatie oplevert. Met een gecontroleerde purge verwijder ik alleen wat echt opnieuw moet worden weergegeven, houd ik de caches warm en bespaar ik Serverbelasting. Wijzigingen met grotere gevolgen kan ik beter in een kort Optimalisatievenster, zodat de server bij het herladen geen last heeft van piekbelastingen. Zo blijft de pagina snel en voorkom ik visuele fouten die vaak voortkomen uit verouderde HTML- of JSON-antwoorden.

Strategieën voor het ongeldig maken van de cache: afloop, key-purge en volledige wipe

Ik combineer drie methoden om op een zinvolle manier gegevens te verwijderen: vervaltermijnen (expiration) voor inhoud die van nature veroudert, gerichte key-purge voor bepaalde URL’s en het volledig wissen van een zone na structurele wijzigingen. Ik stel de vervaltermijn kort in voor zeer dynamische pagina’s en langer voor statische landingspagina’s, zodat Slagingspercentages hoog blijven. Ik voer de Key-Purge uit zodra een bericht of een menu is opgeslagen, en neem daarbij naast de individuele URL ook de betreffende archieven of de startpagina mee. De volledige wipe bewaar ik voor het wisselen van sjablonen, ingrijpende aanpassingen aan plug-ins of cache-corruptie. De volgende tabel helpt me om snel de juiste aanpak te kiezen en de risico’s realistisch in te schatten.

Strategie Besturingssysteem Sterke punten Risico's Typisch gebruik
Vervaldatum inactief, max_age Weinig moeite Verouderde inhoud tot de vervaldatum Archiefpagina's, pagina's die zelden worden gewijzigd
Key-Purge specifieke URL/sleutel Gedetailleerd en snel Verkeerde sleutels werken niet Update van de bijdragen, wijziging in het menu
Wildcard-opschoning Voorvoegsel met * Groep verwijderen Te veel gewist Series, categorie-clusters
Alles wissen Zone leegmaken Gecoördineerde herstart Hoge belasting tijdens het bijvullen Van sjabloon/thema wisselen

FastCGI-cache op het bestandssysteem: configuratie, zones en limieten

Ik configureer de FastCGI-cache met fastcgi_cache_path Stel een duidelijke opslaglocatie in (bijv. /var/cache/nginx/fastcgi), kies niveaus zoals 1:2 voor platte mappen en wijs een `keys_zone` toe met een duidelijke naam en een geschikte grootte. De inactiviteitsduur en een bovengrens voorkomen een te grote footprint en houden de SSD soepel. NGINX slaat hier hash-bestanden op die zonder hulpmiddelen nauwelijks handmatig te ordenen zijn; daarom plan ik van tevoren hoe ik ze ga verwijderen: afzonderlijke sleutels via modules of scripts, complete zones via systematische commando’s. Voor WordPress-stacks loont deze opzet zich in de vorm van een meetbaar lagere TTFB, vooral bij niet-gecachete eerste verzoeken na een deployment. Wie zich verder verdiept in prestatie-optimalisatie, vindt aanvullende ideeën onder Snelheid van WordPress en kan deze koppelen aan de eigen purge-regels.

Stampedes voorkomen en Stale op een zinvolle manier gebruiken

Tijdens het purgen of na het verstrijken van de time-outs mag er geen pieksituatie ontstaan voor PHP-FPM. Daarom schakel ik locks en stale-strategieën in: een eerste verzoek bouwt het object opnieuw op, parallelle verzoeken wachten even (lock), en bij fouten of time-outs lever ik uit een gedefinieerde voorraad (use_stale). Achtergrondupdates houden veelgebruikte paden actueel, zonder de lezer te vertragen.

# Cache-storm voorkomen en gebruikmaken van grace-tijden
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout   5s;
fastcgi_cache_lock_age 10s;

fastcgi_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
fastcgi_cache_background_update on;

# zinvolle standaardtijden
fastcgi_cache_valid 200 301 302 10m;
fastcgi_cache_valid 404 1m;   # Fouten slechts kort vasthouden

Zo verminder ik CPU-pieken en voorkom ik dat kortstondige piekjes in de backend hele onderdelen vertragen. Vooral bij grote opschoningen of implementaties is deze beveiliging de moeite waard, omdat de opwarmfasen beheersbaar en voorspelbaar blijven.

Veilig opschonen: scripts, controles en zorgvuldig bereik

Op productieve systemen laat ik purge-scripts alleen draaien met wortel uitvoeren en zorg ik voor een strikte validatie van het pad, zodat er geen verkeerde mappen worden verwijderd. Voordat er iets wordt verwijderd, controleert mijn script of de variabele voor het doelpad is ingesteld en gekoppeld is aan de verwachte cachemap; anders wordt het proces afgebroken. Ik bied de tool twee modi aan: gerichte sleutelverwijdering (bestand op basis van hash) en gecontroleerd leegmaken van de zone, waarbij ik voor de tweede modus een extra bevestiging vraag. Logs registreren elke verwijdering met een tijdstempel, zodat ik later de oorzaak-gevolgrelatie duidelijk kan traceren. Hoe minder ik globaal verwijder, hoe sneller de cache ‘warm’ blijft, en dat is precies waar mijn Strategie van.

HTTP-Purge via modules: gericht, automatiseerbaar en traceerbaar

Als er geen native interface is, gebruik ik een extra module zoals ngx_cache_purge en verwerk ik PURGE-verzoeken via een eigen location, die dezelfde Cache-sleutel wordt berekend zoals bij GET. De module verwijdert vermeldingen voor afzonderlijke URL's, kan met jokertekens groepen verwijderen en biedt als laatste stap de mogelijkheid om een complete zone te leegmaken. Toepassingen zoals WordPress activeren na het opslaan van een bericht automatisch opschoningen voor de URL van het bericht, de startpagina en de betreffende archieven, wat zorgt voor actualiteit zonder handmatige ingrepen. Ik beperk jokertekens strikt tot unieke voorvoegsels, omdat te brede patronen onnodig veel objecten verwijderen. Voor bijzonder kortstondige inhoud is het bovendien de moeite waard om een Microcaching-aanpak, die secondencaches op een slimme manier combineert met PURGE.

De toegang tot Purge-eindpunten beveiligen

Als er een HTTP-eindpunt is, beveilig ik dat grondig: toegang alleen vanaf interne IP-adressen zoals 127.0.0.1 of een admin-VPN-adres, aangevuld met HTTP-authenticatie met een sterk wachtwoord. Ik gebruik niet voor de hand liggende padnamen, log elk PURGE-verzoek en beperk de frequentie, zodat er niet onbedoeld golven de backend bereiken. De locatie staat uitsluitend de PURGE-methode toe, evenals GET voor statusverzoeken; al het andere blokkeer ik. Zo voorkom ik misbruik en zie ik in het logboek direct welke applicatie wanneer welke URL ongeldig heeft gemaakt. Veiligheid gaat hier boven gemak, want een open endpoint kan Aanvallen uitnodigen.

WordPress-integratie: hooks, doel-URL’s en cachinglogica

In WordPress koppel ik purges aan hooks die worden geactiveerd bij wijzigingen, bijvoorbeeld bij het opslaan van een bericht of bij het aanpassen van een menu. De hook activeert verzoeken voor alle direct betrokken URL's: individuele berichten, de eerste pagina van de categorie, de startpagina en, indien aanwezig, relevante tagarchieven, zodat bezoekers direct de juiste inhoud te zien krijgen. Ik vermijd het globaal leegmaken bij kleine bewerkingen, anders gaat het voordeel van een warme cache verloren en de Reactietijden variëren. Voor meertalige en gepersonaliseerde onderdelen maak ik een duidelijk onderscheid tussen welke cookies daadwerkelijk invloed hebben op de HTML-uitvoer, zodat de sleutel niet onnodig wordt opgesplitst. Met een duidelijke purge-lijst en spaarzaam gebruik van jokertekens blijft het systeem snel en tegelijkertijd betrouwbaar up-to-date.

WordPress-voorbeelden: hooks, URL-selectie en rollback

Voor schone purges definieer ik per gebeurtenis een kleine, maar volledige verzameling URL’s. Bij het opslaan van een bericht hoort daarin ten minste: de permalink-URL van het bericht, de startpagina (als daarop de meest recente berichten worden weergegeven), de eerste categoriepagina, eventueel tagarchieven, en JSON-feeds. Bij menu’s komen daar bovendien alle pagina’s bij die het menu weergeven (vaak globaal: startpagina, archiefpagina’s, 404).

// Pseudocode: Purge-doelen na het bijwerken van een bericht
on save_post($post_id) {
  $urls = [
    get_permalink($post_id),
    home_url('/'),
    get_category_link(primary_category($post_id)),
    get_tag_link(primary_tag($post_id)),
    home_url('/feed/'),
  ];
  purge_urls(array_unique(array_filter($urls)));
}

// Purge-handler roept het beveiligde PURGE-eindpunt aan
function purge_urls($urls) {
  foreach ($urls as $u) {
    http_request('PURGE', internal_purge_endpoint($u));
  }
}

Ik houd rollback-gevallen goed in de gaten: als een status verandert van ‘Concept’ naar ‘Gepubliceerd’ of andersom, pas ik de purge-lijst dienovereenkomstig aan (archiefpagina’s, startpagina). Bij grootschalige wijzigingen (importen, het hernoemen van termen) bundel ik de purge-acties en spreid ik ze uit over korte tijdsperiodes om pieken in de belasting te voorkomen.

E-commerce- en sessiegevallen correct afhandelen

Webwinkels en andere sessiegevoelige onderdelen vereisen strikte regels: het winkelmandje, het afrekenproces en de account-/inlogpagina’s mogen niet in de cache worden opgeslagen. Ik regel dit via cookie-patronen (bijv. woocommerce_items_in_cart), nauwkeurige locatiematches (/cart, /checkout, /my-account) en stel daar fastcgi_no_cache en bypass Op productpagina’s kan daarentegen uitstekend worden gecachet, zolang prijs- en voorraadinformatie niet per gebruiker verschilt. Voor kortstondige meldingen (bijv. „toegevoegd aan het winkelmandje“) los ik dit aan de clientzijde op en houd ik HTML-varianten beknopt.

Best practices voor productieve omgevingen

Ik begin met een duidelijke Cache-strategie: korte geldigheidsduur voor de voorpagina, blogindex of winkeloverzichten, langere geldigheidsduur voor statische pagina’s en documentatie. Vervolgens stel ik purge-regels in die bij inhoudelijke wijzigingen slechts gericht gegevens verwijderen, terwijl deployments een gecontroleerde, grotere purge in gang zetten. Elke release voorzie ik van X-FastCGI-Cache: HIT, MISS of BYPASS als header, zodat ik in de browser of via curl kan zien wat er daadwerkelijk uit de cache kwam. Ik houd de cachezone in de gaten op basis van grootte en aantal bestanden, zodat ik knelpunten kan herkennen en limieten tijdig kan aanpassen. Voor assets zoals CSS/JS gebruik ik versiebeheer in bestandsnamen, waardoor het leegmaken van de cache voor statische bestanden vaak overbodig wordt en de Verkeer afneemt.

Hostingscenario's: shared, managed en eigen server

In shared-omgevingen regel ik purges meestal via een paneel of plug-in, omdat ik geen directe toegang tot NGINX heb en op deze manier toch de actualiteit kan waarborgen. Managed WordPress-hosts integreren caching vaak diep in hun platform; in dat geval houd ik me aan hun richtlijnen en controleer ik hoe automatische purges zijn gekoppeld aan CMS-gebeurtenissen. Op een VPS of dedicated server neem ik de volledige controle over: configuratie, Scripts, eindpunten, beveiliging en monitoring. Bij een hoge belasting en veel redacteuren is deze controle de moeite waard, omdat ik zo een goed evenwicht vind tussen prestaties en actualiteit. Wie de voorkeur geeft aan een krachtig platform met goede NGINX-caching, kan aanbiedingen zoals webhoster.de bekijken en de beschreven workflows direct toepassen.

Voorverwarmen na het spoelen: gecontroleerd en zuinig met hulpbronnen

Na gerichte opschoningen verwarm ik bewust ‘hot paths’, in plaats van de kosten door te berekenen aan bezoekers. Dat doe ik met een klein script dat belangrijke URL's achtereenvolgens oproept en tussendoor pauzes inlast. Daarbij let ik op HEAD/GET, HTTP/2-connectiviteit en lage gelijktijdigheid, zodat PHP-FPM niet overbelast raakt.

# Voorbeeld: opwarmen via een lijst met URL's
#!/bin/bash
URLS=("https://example.com/" "https://example.com/blog/" "https://example.com/kategorie/foo/")
for u in "${URLS[@]}"; do
  curl -s -I "$u" >/dev/null
  sleep 0.2
done

Voor omvangrijkere websites genereer ik de lijst op basis van sitemaps of CMS-exports, groepeer ik deze in batches en verdeel ik de opstarttaak over tijdsvensters van enkele minuten. Bij implementaties start ik het voorverwarmen kort na de gerichte opschoningen, zodat lezers tijdens de piekuren snel worden bediend.

Monitoring en logboekregistratie inschakelen

Transparantie is een must. Ik breid het NGINX-logformaat uit met de cache-status en maak een onderscheid tussen access- en purge-logs. Zo herken ik patronen (veel BYPASS als gevolg van cookieregels, een toename van MISS na implementaties) en kan ik de limieten verder aanscherpen.

# Toegangslogboeken met cache-status
log_format main '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent '
 '"$http_referer" "$http_user_agent" '
                'rt=$request_time uct=$upstream_connect_time '
 'uht=$upstream_header_time urt=$upstream_response_time '
 'cache=$upstream_cache_status';

access_log /var/log/nginx/access.log main;

# Voorbeeldanalyse
# grep 'cache=HIT' /var/log/nginx/access.log | wc -l
# grep 'cache=BYPASS' /var/log/nginx/access.log | wc -l

Daarnaast houd ik de cachezone (aantal bestanden, bytes), het inode-gebruik en de I/O-waarden in de gaten. Als het hitpercentage daalt, controleer ik eerst: is de sleutel onbedoeld gewijzigd, zijn er te veel cookies in het spel, zijn er nieuwe queryparameters geïntroduceerd of blokkeren bypass-regels onverwacht?

Omgevingen met meerdere locaties en domeinen

Bij netwerken met meerdere domeinen scheid ik zones of kapsel ze netjes per host in de sleutel. Voor bijzonder grote tenants gebruik ik aparte keys_zone-vermeldingen, zodat hot-sites niet het gehele geheugen in beslag nemen. Het opschonen organiseer ik per site: de WordPress-hook bepaalt lokaal welke URL’s ongeldig worden gemaakt; de eindpunten zijn op identieke wijze beveiligd. Staging en productie scheid ik strikt via verschillende zones/mappen, zodat er geen cross-purges plaatsvinden.

Foutmeldingen voorkomen: van bypass tot Purge All

Veel problemen ontstaan door te ruime bypass-regels, die bij bepaalde Cookies de cache volledig omzeilen en het trefpercentage verpesten. Ik beperk uitsluitingen tot een minimum en controleer met testaccounts of personalisatie echt server-rendering vereist of via JavaScript kan worden uitgevoerd. Een permanente ‘Purge All’ vertraagt elke pagina, daarom gebruik ik deze functie alleen na structurele aanpassingen en buiten de piekuren. Een gebrek aan transparantie belemmert de diagnose, daarom activeer ik vanaf het begin duidelijke headers en logs en test ik wijzigingen op een reproduceerbare manier op de staging-omgeving. Als er geen resultaten worden gevonden, onderzoek ik de sleutels, controleer ik de antwoordheaders, vergelijk ik de host-/URI-normalisatie en kijk ik naar de cachegroottes en Inactiviteit-timer.

Samenvatting in het kort

Met een schone Cache-sleutel, dankzij slimme vervaltermijnen en gerichte opschoningen houd ik pagina’s snel en de inhoud correct. Scripts met padcontroles en strenge eindpuntbeveiliging voorkomen misbruik en vermijden het per ongeluk wissen van gegevens. WordPress-hooks zorgen voor de juiste automatisering, zonder dat de hele cache na elk kleinigheidje hoeft te worden geleegd. Monitoring via de X-FastCGI-cache, logbestanden en zonegroottes laat me zien waar ik nog wat moet bijschaven en of mijn workflow goed functioneert. Wie deze punten ter harte neemt, combineert hoge snelheid met betrouwbare actualiteit – de basis voor een soepele Levering op elke website die op PHP draait.

Huidige artikelen