...

HTTP-voorwaardelijke caching met ETag en Last-Modified begrijpen

HTTP-caching bespaart tijd en data doordat ik bronnen alleen opnieuw laad als ze daadwerkelijk zijn gewijzigd. Via ETag en Laatst gewijzigd controleer ik via een voorwaardelijke verzoek of de server met 304 Not Modified reageert, waardoor de datatransmissie en de belasting van de server aanzienlijk afnemen.

Centrale punten

De volgende kernpunten laten zien waar ik bij conditional caching op let met ETag en Laatst gewijzigd attentie.

  • Minder verkeer: Ongewijzigde bestanden retourneren een 304-statuscode in plaats van de volledige body – dit vermindert het dataverkeer en de latentie aanzienlijk.
  • Betere prestaties: Kortere wachttijden komen de gebruikerservaring en de Core Web Vitals ten goede, wat SEO helpt.
  • Twee mechanismen: Last-Modified/If-Modified-Since en ETag/If-None-Match zorgen voor een betrouwbare validatie van de cache.
  • Cachebeheer: Richtlijnen regelen de verversingsfrequentie, het herstel en het gedrag in tussencaches.
  • Combinatie: Beide methoden samen bieden een hoge nauwkeurigheid en eenvoudige alternatieve oplossingen.

Ik kijk eerst welke bestanden vaak worden gewijzigd en welke zelden. Voor bestanden die zelden worden gewijzigd, stel ik een Laatst gewijzigd-tijdstip en voeg een ETag toe. Voor dynamische antwoorden geef ik de voorkeur aan de ETag, omdat elke inhoudelijke wijziging direct zichtbaar is. Zo ontlast ik de servers, verminder ik de vertragingstijden en bied ik terugkerende bezoekers zeer snelle pagina’s. Deze strategie versterkt de Kernwaarden Web Vitals en daarmee indirect de zichtbaarheid.

HTTP-voorwaardelijke caching: zo controleer ik de geldigheid

Bij een nieuwe verzoek stuurt de client naast GET extra headers mee, die ik aan de serverzijde verwerk. Heeft de bron dezelfde ETag als het in de cache staat (If-None-Match), stuur ik een 304 Not Modified zonder body. Als er niets is veranderd aan de tijdstempel (If-Modified-Since), reageert de server eveneens met 304. Als de dag of datum niet meer klopt, stuur ik 200 OK met nieuwe inhoud plus bijgewerkte Laatst gewijzigd en ETag. Zo bespaar ik bandbreedte, houd ik de cache up-to-date en zorg ik voor merkbaar snellere laadtijden.

Last-Modified en If-Modified-Since in de dagelijkse praktijk

De koptekst Laatst gewijzigd Ik baseer me op het daadwerkelijke wijzigingstijdstip van het bestand, bijvoorbeeld uit het bestandssysteem. Als er later een verzoek komt met If-Modified-Since en de bron is sindsdien niet gewijzigd, stuur ik een 304-antwoord. Deze methode is eenvoudig, goed te begrijpen en ideaal voor statische assets zoals CSS, JS of afbeeldingen. Beperkingen zijn het secondenraster van HTTP-tijdstempels en situaties waarin inhoud logisch verandert zonder dat er een duidelijk bestandstijdstip bestaat. Waar Last-Modified zijn grenzen bereikt, vult een ETag de controle.

ETag en If-None-Match in dynamische systemen

A ETag Ik genereer deze als hash, versie-ID of uit een databasekolom die statuswijzigingen aangeeft. Bij hernieuwde toegang stuurt de browser If-None-Match, ik vergelijk de tag met mijn huidige waarde en antwoord dienovereenkomstig met 304 of 200. Deze vergelijking herkent elke zinvolle inhoudswijziging, zonder te vertrouwen op tijdstempels van bestanden. Vooral bij API's, samengestelde pagina's of gepersonaliseerde fragmenten levert dit zeer nauwkeurige resultaten op. Het blijft belangrijk dat ik ETags in clusteromgevingen consistent houd, zodat geen enkele server per ongeluk een andere Dag geproduceerd.

Cache-Control correct combineren

Met Cachebeheer Hiermee bepaal ik hoe lang inhoud zonder navraag als actueel wordt beschouwd en wanneer de browser deze opnieuw valideert. Ik stel passende max-age-waarden in, afhankelijk van de frequentie van wijzigingen, en gebruik must-revalidate wanneer verouderde gegevens kritieke gevolgen zouden hebben. Voor bestanden met versies is een lange geldigheidsduur geschikt, terwijl vaak veranderende antwoorden een kortere levensduur hebben en vervolgens netjes kunnen worden gecontroleerd via ETag of datum. Zo combineer ik korte responstijden met de juiste actualiteit. Wie zich hier verder in wil verdiepen, vindt veel voorbeelden onder Cache-Control-strategieën, die ik in de praktijk gebruik.

Het verloop van een Conditional GET stap voor stap

Bij de eerste verzoek stuurt de server een 200 OK-statuscode met Cache-Control, Laatst gewijzigd en ETag; de browser slaat alles op. Bij het volgende bezoek bepaalt de ouderdom in de cache of een hervalidatie nodig is. Als dat het geval is, vraagt de browser dit aan met If-None-Match en/of If-Modified-Since. Als de waarden overeenkomen met de huidige status, stuur ik 304 Not Modified, de client blijft zijn cache gebruiken. Als ze niet meer kloppen, volgt 200 OK met een nieuwe body en bijgewerkte Validatiegegevens.

Vergelijking: ETag versus Last-Modified

Beide methoden geven mij controle, maar verschillen qua inspanning, nauwkeurigheid en geschiktheid. Laatst gewijzigd scoreert door de eenvoudige implementatie en duidelijke semantiek, zolang ik maar over zuivere tijdstempels beschik. De ETag geeft de inhoud zeer nauwkeurig weer, maar vereist wat logica om te genereren. In veel opstellingen combineer ik beide en profiteer ik zo van eenvoud plus nauwkeurige herkenning. De volgende tabel vat typische kenmerken samen en helpt bij het maken van een keuze.

Aspect Laatst gewijzigd ETag Tip
Identiteit Tijdstempel van de laatste wijziging Inhoudshash of versie-ID Tijd vs. inhoudsgebaseerde identificatie
Wijzigingsdetectie Resolutie tot op de seconde, indirect Direct gericht op de inhoud ETag detecteert de kleinste Verschillen
implementatie Zeer licht, het bestandssysteem is voldoende Vereist generatie en consistentie Clusters hebben hetzelfde nodig ETags
Gebruik Statische bestanden Dynamische antwoorden Deze combinatie dekt veel gevallen van
Antwoorden 304 met ongewijzigde tijdstempel 304 bij dezelfde tag 200 bij wijzigingen met een nieuwe Waarde

Praktijk: statische assets efficiënt leveren

Statische bestanden zoals CSS, JS en afbeeldingen veranderen zelden en zijn geschikt voor lange maximumleeftijd-tijden. Voor bestanden met versiebeheer stel ik lange tijden in, tot wel een jaar, en markeer ik ze als ‘immutable’, zodat de browser ze zonder vragen laadt. Voor niet-versiebeheerde assets kies ik kortere termijnen en vertrouw ik op hervalidatie via ETag en Last-Modified. Zo voorkom ik verouderde inhoud en houd ik het verkeer laag. Als ik ervoor zorg dat ik geen Sabotage cache header door dit te doen, bereik ik een hoog trefpercentage in de cache.

Praktijk: API's en dynamische pagina's

Als het om API's gaat, kies ik meestal voor ETags, die ik samenstel uit het geserialiseerde resultaat of een versiekolom. Als het gegevensrecord verandert, genereer ik een nieuwe tag; clients herkennen dit onmiddellijk. Voor inhoud met een onzekere tijdstempel laat ik Last-Modified vaak achterwege, zodat er geen verkeerde indruk van actualiteit ontstaat. Daarnaast regel ik de levensduur via Cache-Control en dwing ik na het verstrijken ervan tot hervalidatie. Zo houd ik gegevens betrouwbaar actueel, zonder antwoorden onnodig groot te maken.

Testen en monitoren van de cache-hitratio

Ik controleer headers zoals ETag, Last-Modified, If-None-Match en If-Modified-Since in de Developer Tools. Daarbij let ik op de responscodes, met name 304 versus 200, om de effectiviteit van mijn hervalidatie te beoordelen. Als 304 zelden voorkomt, pas ik Cache-Control, geldigheidsduur en de ETag-generatie aan. Logs en statistieken laten me zien welke paden onnodig grote antwoorden geven. Voor gebundelde verbeteringen maak ik graag gebruik van een Conditional-Requests-pakket, dat configuratie en tests samenbrengt.

Hostingarchitectuur en ETag-valkuilen

In opstellingen met meerdere servers moet een ETag onafhankelijk zijn van de instantie, anders mislukt de herkenning. Ik zorg ervoor dat alle knooppunten dezelfde logica en dezelfde sleutel gebruiken voor het genereren. Reverse proxies of CDN’s mogen ETags niet wijzigen en moeten conditie-headers correct doorgeven. Bij implementaties met asset-vingerafdrukken vermijd ik het opnieuw berekenen van ETags aan de serverzijde als het bestand al een URL met versienummer heeft. Uniforme regels voorkomen inconsistente antwoorden en houden de cache-hitrate hoog.

Versheid versus validatie: richtlijnen nauwkeurig toepassen

Ik maak een duidelijk onderscheid tussen Versheid (hoe lang mag een cache een kopie gebruiken zonder navraag?) en Validatie (hoe kan ik controleren of deze nog geldig is?). Via Cachebeheer Ik regel beide heel gedetailleerd: maximumleeftijd bepaalt de levensduur bij de client, s-maximum voor gedeelde caches zoals proxyservers. openbaar maakt caching in gedeelde caches mogelijk, privé beperkt het tot de eindbrowser. moet opnieuw worden gevalideerd dwingt tot navraag na afloop, terwijl onveranderlijk voorkomt onnodige hervalidaties bij assets met versiebeheer. no-cache verbiedt caching niet, maar vereist altijd een hervalidatie; geen opslag verbiedt daarentegen het opslaan volledig. Oudere Verloopt op-Headers gebruik ik alleen als noodoplossing; ik verplaats de logica consequent naar Cache-Control. En als ik storingen wil opvangen, helpen stale-while-revalidate en stale-if-error, om inhoud die op korte termijn is verlopen door te geven, terwijl ik op de achtergrond updates uitvoer of fouten omzeil.

Sterke en zwakke ETags, compressie en varianten

Ik maak bewust onderscheid tussen sterke en zwakke validatoren. Sterke ETags identificeren die tot op de byte nauwkeurig dezelfde weergave is – ideaal als ik ook Bereik Verzoeken efficiënt wil bedienen. Zwakke ETags (voorvoegsel W/) volstaan wanneer semantische gelijkheid voldoende is, bijvoorbeeld bij kleine, irrelevante wijzigingen in de opmaak. Belangrijk is de omgang met Compressie: Als ik zowel gzip- als brotli-gecomprimeerde inhoud lever, mag één enkele ETag niet voor alle varianten gelden. Ik moet de tag ofwel op basis van de ongecomprimeerde versie genereren en daarnaast een passende Vary: Accept-Encoding, of ik genereer per variant consistente, maar verschillende ETags. Zo voorkom ik foutieve resultaten en 200-responsen die eigenlijk 304 zouden moeten zijn. Bij Als-bereik Ik combineer bereikverzoeken met een validator: als de ETag of datum klopt, stuur ik een 206 Partial Content terug; anders stuur ik een 200 met volledige body, zodat de client een consistente basis heeft.

Vary-headers en content-negotiation goed onder de knie krijgen

Telkens wanneer de server, afhankelijk van de vereisten, verschillende weergaven levert, stel ik Variëren juist. Typische voorbeelden zijn Accept-Encoding (compressie), Accept-Language (lokalisatie) of specifieke feature-flags. Ik vermijd het gebruik van vluchtige headers zoals Gebruiker agent of zelfs Cookie te variëren, omdat dat de cache-hitrat enorm omlaag haalt. Waar personalisatie nodig is, markeer ik antwoorden als privé of geen opslag en maak een duidelijk onderscheid tussen deze en bronnen die openbaar in de cache kunnen worden opgeslagen. Belangrijk: variaties hebben ook invloed op ETags – elke variant heeft zijn eigen, consistente validator nodig. Zo zorg ik ervoor dat browsers, proxyservers en CDN’s dezelfde logica toepassen en dat geen enkele variant per ongeluk met een andere wordt verward.

Voorwaardelijke verzoeken die verder gaan dan GET

Voorwaardelijke verzoeken werken niet alleen bij het lezen. Voor schrijfmethoden gebruik ik Als-match of If-Unmodified-Sinceom gemiste updates te voorkomen. Als de client bij een PUT- of DELETE-verzoek de laatst waargenomen ETag verstrekt via Als-match als de serverstatus nog steeds hetzelfde is, voer ik de wijziging pas door – anders antwoord ik met 412 Voorwaarde niet vervuld. Om clients in het gareel te houden, kan de server bovendien 428 Voorwaarde vereist invoeren. Voor snelle tests zonder body gebruik ik HEAD, dat me dezelfde headers geeft als een GET-verzoek; ideaal als ik metadata wil testen. En bij 304-In mijn antwoorden voeg ik alle voor de cache relevante headers opnieuw toe (Cache-Control, ETag, Expires, Last-Modified), zodat de client zijn metadata bijwerkt zonder de body te verzenden.

Beveiliging, gegevensbescherming en compliance

Persoonsgegevens of gevoelige inhoud sla ik niet op in de openbare cache. Hier gebruik ik Cachebeheer: privé of geen opslag, zodat de browser of een andere instantie de inhoud niet opslaat. Wees voorzichtig met gebruikersaccounts en dashboards: antwoorden met Cookie instellen of Autorisatie mogen niet per ongeluk openbaar cachebaar zijn. ETags zelf kunnen als tracking-vector worden misbruikt als ze gedurende lange tijd stabiel blijven. Ik ga dit tegen door validators alleen actief in te zetten waar caching ook gewenst is, en ze uit te schakelen bij gebruikersspecifieke routes of de levensduur kort te houden. Zo combineer ik prestaties met privacyvereisten.

Implementatiedetails en prestatiekosten

Het genereren van een ETag mag niet duurder zijn dan het nut ervan. Voor grote bestanden of dure renderings sla ik de tag samen met metadata op (bestandschecksum, build-hash, database-rijversie) en herhaal dit niet bij elk verzoek. Bij samengestelde pagina’s helpt een Strategie voor het samenstellen van versies: Ik stel de ETag samen uit stabiele sub-ETags (bijv. sjabloon, gegevensfragment, configuratie), zodat kleine wijzigingen een gerichte, maar reproduceerbare nieuwe waarde opleveren. In clusters synchroniseer ik de generatielogica in een gemeenschappelijke bibliotheek en controleer ik deze in CI, zodat geen enkele instantie afwijkt. Voor extreem grote blobs gebruik ik snelle checksums (CRC64) of sla ik build-hashes op, in plaats van de body on-the-fly te hashen. Waar absolute byte-gelijkheid niet nodig is, volstaan zwakke ETags als pragmatisch compromis.

Veelgemaakte fouten en hoe ze te vermijden

  • Willekeurige ETags: Als tags bij elk verzoek opnieuw worden gegenereerd, heeft elke hervalidatie geen zin. Ik zorg voor deterministische waarden die alleen veranderen als er daadwerkelijk iets verandert.
  • Verkeerde combinatie van richtlijnen: geen opslag ETag heeft geen zin – de browser slaat het toch niet op. Ik kies consistente combinaties voor het gewenste gedrag.
  • Overmatig Vary: Variaties op de cookie of user-agent breken de cache af. Ik beperk Vary tot echte wijzigingen in de weergave.
  • Compressievallen: Een gemeenschappelijke ETag voor gzip en br leidt tot foutieve resultaten. Ik koppel ETags correct aan de specifieke variant en stel Vary correct in.
  • Tijdsverschuiving: Onnauwkeurige serverklokken verstoren de Last-Modified-waarde. Ik houd de tijdbronnen gesynchroniseerd, zodat If-Modified-Since correct werkt.
  • Verwarring met no-cache: Veel mensen lezen „niet cachen“. Wat ermee bedoeld wordt, is „altijd opnieuw valideren“. Voor een echt verbod gebruik ik geen opslag.

Probleemoplossing, statistieken en workflows

Om fouten op te sporen, begin ik op het tabblad Netwerk: Klopt Cachebeheer? Komt bij revalidatie 304 in plaats van 200? Past ETag en Laatst gewijzigd tussen vraag en antwoord? Ik controleer het Variëren, om te controleren of varianten correct worden herkend. In de logbestanden laat ik Raak/Miss-quota, 304-percentages en gemiddelde responsgroottes per pad weergeven. Als het 304-percentage stijgt, dalen het datavolume en de TTFB doorgaans merkbaar. In belastingstests simuleer ik herhaalde verzoeken om revalidatiekosten in plaats van overdrachtskosten te meten. Bij afwijkingen verwijder ik stapsgewijs storende factoren: Set-Cookie, te strenge Vary-regels, tegenstrijdige headers zoals Pragma. Zo vind ik snel de bottleneck die de hitrate drukt.

Service Worker als aanvullende cachelaag

Als ik een service worker gebruik, zet ik die in als een extra laag, niet als een tegenstrijdige laag. Ik laat hem dezelfde Cachebeheer-Signalen respecteren en strategieën combineren zoals stale-while-revalidate bewust met HTTP-validatie via ETag en Last-Modified. In offline situaties kan de worker tijdelijk verouderde bronnen leveren en deze op de achtergrond opnieuw valideren. Het blijft belangrijk dat hij de conditie-headers correct doorgeeft, anders verlies ik de voordelen van 304 op het netwerk. Zo profiteren ook PWA-scenario's van nette HTTP-caching, in plaats van de mechanismen ervan te omzeilen.

SEO-effect en Core Web Vitals

Snelle antwoorden verbeteren UX en gebruikerssignalen, wat de rankings ten goede komt. Vooral terugkerende bezoekers profiteren hiervan, omdat hun browser veel bestanden direct uit de cache of via een 304-status opvraagt. Deze lagere latentie heeft een positief effect op FCP, LCP en TTFB, die ik door gerichte hervalidatie verder verlaag. Bovendien bespaart de server rekenkracht, die ik kan gebruiken voor pieken in het verkeer of veeleisende verzoeken. Zo blijf ik performant, terwijl de inhoud correct en tijdig wordt weergegeven.

Samenvatting: Mijn stappenplan

Ik vertrouw op een duidelijke Combinatie op basis van Cache-Control, Last-Modified en ETag. Voor statische bestanden kies ik lange geldigheidsduur en zorg ik voor hervalidatie als bestanden niet van een versie zijn voorzien. Voor dynamische antwoorden genereer ik betrouwbare ETags en houd ik clusters consistent. Vervolgens controleer ik met tools, metrics en logs of 304 vaak genoeg voorkomen en pas ik instellingen aan. Zo zorg ik voor snelle levering, lagere belasting en een betere gebruikerservaring door effectieve HTTP-caching.

Huidige artikelen

Datacenter met onderling verbonden databaseservers voor een replicatietopologie
Databases

Databasereplicatietopologieën bij hosting begrijpen en optimaal benutten

Uitgebreide gids over databasereplicatietopologieën bij hosting: ontdek hoe je de juiste replicatieconfiguratie kunt plannen voor de prestaties, hoge beschikbaarheid en schaalbaarheid van je databases. Met de nadruk op databasereplicatietopologieën voor moderne webprojecten.