Cache-Control — wat is het, directives en cachebeheer

Auteur: IT Sectr Gepubliceerd: 2026-03-09 Leestijd: 9 min

Cache-Control — een HTTP-header die de cacheringsregels van resources aan de clientzijde, proxyservers en CDN’s bepaalt met behulp van een set directives. In tegenstelling tot de verouderde Expires-header ondersteunt Cache-Control tientallen combinaties: max-age stelt de levensduur in seconden in, private en public beheren de beschikbaarheid van de cache, no-cache en no-store — gedwongen controle. Volgens Google Web Dev (2025) kan een juiste configuratie van Cache-Control de laadtijd van pagina’s met 50-80% verminderen voor herhaalde bezoeken. Dit maakt de header kritisch voor de prestaties van web- en mobiele applicaties.

Belangrijkste punten

  • Cache-Control — HTTP-header met directives die caching op client, proxy en CDN beheren
  • max-age — belangrijke directive die de levensduur van een resource in seconden instelt zonder herhaalde controle
  • private vs public — private staat cache alleen op de client toe, public ook op proxy en CDN
  • no-cache vs no-store — no-cache vereist controle voor gebruik, no-store verbiedt caching volledig
  • s-maxage — overschrijft max-age voor gedeelde (shared) caches, zonder browsers te beïnvloeden

Wat is Cache-Control?

Cache-Control — een HTTP-header, gestandaardiseerd in HTTP/1.1 (RFC 7234), waarmee de server kan aangeven hoe en hoe lang clients, proxies en CDN’s het antwoord mogen cachen. In tegenstelling tot Expires (HTTP/1.0) gebruikt Cache-Control directives — tekstuele opdrachten die door komma’s worden gescheiden: Cache-Control: public, max-age=3600, must-revalidate. De header biedt fijnmazige controle over elke schakel in de cacheringsketen.

Caching is een van de fundamentele prestatiemechanismen van het web en mobiele applicaties. Zonder caching zou elk gebruikersverzoek rechtstreeks naar de server gaan, wat overmatige belasting en vertragingen veroorzaakt. Cache-Control definieert drie cacheniveaus: browser/app (private cache), proxyservers (shared cache) en CDN (distributed cache). Elk niveau interpreteert de directives op zijn eigen manier.

Onjuiste configuratie van Cache-Control is een van de meest voorkomende oorzaken van prestatieproblemen. Te agressieve caching zorgt ervoor dat gebruikers verouderde gegevens zien. Te zwakke caching leidt tot overmatige serververzoeken en traag laden. Volgens Akamai (2025) vermindert optimalisatie van Cache-Control voor statische inhoud de serverbelasting met 70-90% en verbetert het de laadtijd met 40-60% voor mobiele gebruikers.

Geschiedenis van de header

Cache-Control verscheen in HTTP/1.1 (RFC 2616, 1999) als vervanging voor Expires. Expires had een fundamenteel probleem: het gebruikte een absolute datum die afhing van de tijdzone van de server en de client. Cache-Control loste dit probleem op door over te stappen op relatieve tijd (max-age in seconden vanaf het moment van ontvangst van het antwoord). Later werden in RFC 7234 (2014) nieuwe directives toegevoegd: immutable voor statische bestanden, stale-while-revalidate en stale-if-error voor uitgestelde controle.

Cache-Control directives

Cache-Control omvat meer dan 10 directives, verdeeld over drie groepen: verzoekdirectives (client → server), antwoorddirectives (server → client) en extensies. In de praktijk worden in mobiele ontwikkeling 6-7 basisantwoorddirectives gebruikt die 95% van de cacheringsscenario’s dekken. Laten we elk met voorbeelden en aanbevelingen bekijken.

DirectiveBetekenisVoorbeeld
max-ageLevensduur in seconden vanaf antwoordmomentmax-age=3600 — 1 uur
s-maxagemax-age voor shared cache (proxy, CDN)s-maxage=86400 — 1 dag voor CDN
publicStaat caching voor iedereen toe (inclusief proxy)public, max-age=3600
privateStaat cache alleen toe voor browser/appprivate, max-age=600
no-cacheNiet gebruiken zonder controle (304 verplicht)no-cache
no-storeCaching volledig verbiedenno-store
must-revalidateNa max-age verplicht controleren bij originmax-age=3600, must-revalidate
immutableResource verandert niet (voor versiebeheerde statische bestanden)max-age=31536000, immutable

max-age — de belangrijkste directive. Het verbiedt de client om gedurende een bepaalde tijd een verzoek naar de server te sturen. Voor statische bestanden (CSS, JS, afbeeldingen) wordt max-age meestal ingesteld van 1 dag tot 1 jaar. Voor API-antwoorden — van 0 seconden (altijd verse gegevens) tot 5-10 minuten (referentiegegevens). s-maxage maakt het mogelijk een andere levensduur in te stellen voor CDN en browser: CDN bewaart de kopie 1 dag, de browser — 1 uur.

no-cache vs no-store

Deze twee directives worden vaak verward. no-cache verbiedt caching niet — het vereist controle van de gecachede kopie bij elk gebruik via een conditioneel verzoek (If-Modified-Since of If-None-Match). Als de server 304 antwoordt — gebruikt de client de cache. Bij 200 — werkt hij bij. no-store daarentegen verbiedt het opslaan van het antwoord in welke cache dan ook, inclusief schijf en werkgeheugen. Gebruik no-store alleen voor gevoelige gegevens — tokens, betalingsgegevens, persoonlijke documenten.

Cache-Control vs Expires

De Expires-header (HTTP/1.0) geeft ook de levensduur van een resource aan, maar gebruikt een absolute datum: Expires: Thu, 03 Jul 2026 12:00:00 GMT. Cache-Control max-age — relatieve tijd vanaf het antwoordmoment. Het verschil is cruciaal voor gedistribueerde systemen: als server en client zich in verschillende tijdzones bevinden, kan Expires verkeerd worden geïnterpreteerd. Cache-Control heeft dit probleem niet — 3600 seconden is altijd 3600 seconden.

Wanneer beide headers aanwezig zijn, heeft Cache-Control prioriteit boven Expires. Dit is vastgelegd in RFC 7234: „Als het antwoord Cache-Control met de directive max-age bevat, MOET de ontvanger Expires negeren”. In de praktijk wordt aanbevolen om Expires niet te retourneren voor moderne clients, omdat Cache-Control alle scenario’s van Expires dekt. Voor achterwaartse compatibiliteit met oude proxies en browsers kunnen echter beide headers worden geretourneerd.

Expires is vooral blijven bestaan voor statische inhoud op Nginx en Apache — deze servers voegen automatisch beide headers toe. Als u in uw project Expires zonder Cache-Control tegenkomt, vervang het dan door Cache-Control met max-age: de nauwkeurigheid van cachebeheer neemt toe en de afhankelijkheid van de tijdzone wordt geëlimineerd. Voor migratie volstaat het de server zo te configureren dat hij Cache-Control toevoegt in plaats van Expires.

nginx
# Nginx: Cache-Control voor statische bestanden
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable, max-age=2592000";
}

# Verschillende beleidsregels voor verschillende inhoudstypen
location /api/config {
    expires -1;
    add_header Cache-Control "no-cache, must-revalidate";
}

location /api/static-data {
    expires 5m;
    add_header Cache-Control "public, max-age=300";
}

In de Nginx-configuratie voor statische bestanden (CSS, JS, afbeeldingen) wordt Cache-Control ingesteld op 30 dagen met het attribuut immutable — dit attribuut informeert de browser dat de resource nooit verandert onder deze URL (versiebeheer via hash in de bestandsnaam). API-eindpunten gebruiken no-cache voor dynamische gegevens en public met een korte max-age voor referentiegegevens — veelgevraagde en zelden veranderende lijsten.

Caching in mobiele apps

In mobiele applicaties speelt Cache-Control een bijzondere rol vanwege de beperkingen van mobiele netwerken: hoge latentie, onstabiele verbinding, data limieten. Correcte caching stelt de gebruiker in staat gegevens onmiddellijk te zien, zelfs offline, en ze op de achtergrond bij te werken. OkHttp op Android en URLSession op iOS hebben ingebouwde cachesystemen die rekening houden met Cache-Control.

OkHttp gebruikt CacheInterceptor, dat Cache-Control uit het antwoord leest en automatisch caching beheert. Als de server Cache-Control: max-age=3600 retourneert, zal OkHttp een uur lang geen verzoek naar de server sturen. Na het verlopen van max-age stuurt OkHttp een conditioneel verzoek met If-Modified-Since en If-None-Match. Cache configureren in OkHttp: OkHttpClient.Builder().cache(Cache(directory, maxSize)).

kotlin
fun createCachedClient(cacheDir: File): OkHttpClient {
    return OkHttpClient.Builder()
        .cache(Cache(cacheDir, 10L * 1024 * 1024))
        .addNetworkInterceptor { chain ->
            val response = chain.proceed(chain.request())
            response.newBuilder()
                .header("Cache-Control",
                    "public, max-age=300")
                .removeHeader("Pragma")
                .build()
        }
        .build()
}

De code maakt een OkHttpClient met een cache van 10 MB en overschrijft Cache-Control via NetworkInterceptor. Als de server geen Cache-Control retourneert of Expires gebruikt, voegt de interceptor public, max-age=300 (5 minuten) toe. De interceptor verwijdert de verouderde Pragma-header (HTTP/1.0) voor compatibiliteit. Volgens hetzelfde schema werkt caching op iOS via URLCache.shared met configuratie van memoryCapacity en diskCapacity.

Offline modus en stale-while-revalidate

De directive stale-while-revalidate stelt de gebruiker in staat verouderde cache (stale) te zien terwijl de app op de achtergrond verse gegevens laadt. Dit geeft een effect van onmiddellijke respons: de gebruiker ziet de inhoud meteen en na een seconde wordt deze bijgewerkt. Ondersteund door OkHttp vanaf versie 3.10 en URLCache op iOS 14+. Voorbeeld: Cache-Control: max-age=3600, stale-while-revalidate=300 — 1 uur actuele cache, daarna 5 minuten weergave van verouderde cache met achtergrondupdate.

Voorbeelden van Cache-Control configuratie

Verschillende resourcetypen vereisen verschillende cacheringsstrategieën. Laten we de optimale configuraties bekijken voor typische scenario’s in mobiele ontwikkeling. Voor statische inhoud met een hash in de bestandsnaam (bundle.abc123.js) kan max-age tot 1 jaar met immutable worden ingesteld. Voor API-lijsten die zelden worden bijgewerkt (catalogi, categorieën) — max-age van 5 minuten tot 1 uur met stale-while-revalidate.

ResourcetypeCache-ControlToelichting
Versiebeheerde statische bestandenpublic, max-age=31536000, immutable1 jaar, bestanden veranderen niet (hash in URL)
Niet-versiebeheerde statische bestandenpublic, max-age=86400, must-revalidate1 dag met verplichte controle daarna
API: referentiegegevenspublic, max-age=600, stale-while-revalidate=6010 minuten cache + 1 minuut stale
API: gebruikersgegevensprivate, max-age=601 minuut, alleen voor specifieke gebruiker
API: gevoelige gegevensno-storeCaching volledig verbieden
HTML-pagina’sno-cache, must-revalidateControle bij elk verzoek, 304 bij ongewijzigd

Het is belangrijk om beveiliging in gedachten te houden: stel voor antwoorden met persoonlijke gebruikersgegevens altijd private in. Zonder deze directive kan een openbare proxy (bijvoorbeeld bedrijfsproxy) het antwoord cachen en aan een andere gebruiker doorgeven. Gebruik no-store voor authenticatietokens en betalingsgegevens — zelfs private cache mag deze gegevens niet op schijf opslaan.

Caching debuggen

Gebruik de Age-header (hoeveel seconden de cache is bewaard) en X-Cache (hit/miss op CDN) om de correctheid van Cache-Control te controleren. In de browser — tabblad Network, kolom Size toont „from disk cache” of „304 Not Modified”. Als een resource gecachet zou moeten worden maar telkens wordt geladen — controleer of de server niet Cache-Control: no-cache of Pragma: no-cache toevoegt samen met uw directives.

Veelgestelde vragen

Wat is het verschil tussen max-age en s-maxage?

max-age werkt voor alle caches (inclusief browsers), s-maxage — alleen voor shared cache (proxy, CDN). Als s-maxage is opgegeven, negeert CDN max-age en gebruikt het s-maxage. Dit maakt het mogelijk een verschillende levensduur in te stellen voor browser en CDN.

Kan caching worden geannuleerd na het verzenden van Cache-Control?

Nee, na het verzenden van een antwoord met max-age zal de client geen verzoek doen tot de timer verloopt. Voor onmiddellijke invalidatie van de cache moet u de URL van de resource wijzigen (versie/hash toevoegen) en pushmeldingen of WebSocket-berichten verzenden voor gedwongen reset.

Wat is de immutable directive?

De immutable directive (RFC 8246) informeert de browser dat de resource nooit zal veranderen onder deze URL. De browser probeert niet eens een conditioneel verzoek te sturen bij het verversen van de pagina — hij gebruikt de cache tot het verlopen van max-age. Werkt alleen met versiebeheerde bestanden.

Hoe beïnvloedt Cache-Control SEO?

Googlebot houdt rekening met Cache-Control: lange caching versnelt herhaald scannen. noindex met snelle cache — ok. no-store kan indexering vertragen, omdat Googlebot de pagina elke keer opnieuw zal laden. Een te korte max-age verhoogt de serverbelasting tijdens het scannen.

Hoe configureer ik Cache-Control in Express.js?

Via helmet of middleware: res.set('Cache-Control', 'public, max-age=3600'). Gebruik voor statische bestanden express.static met de parameter maxAge: express.static('public', {maxAge: '1y'}). Voor dynamische routes — individueel in elke handler.

Samenvatting

  • Cache-Control — de belangrijkste HTTP-header voor cachebeheer met een flexibel systeem van directives
  • max-age — levensduur in seconden vanaf het antwoordmoment; belangrijkste directive voor alle cacheringsscenario’s
  • private vs public — private alleen voor client, public voor proxy en CDN; beïnvloedt gegevensbeveiliging
  • no-cache vereist controle, no-store verbiedt caching volledig; verschillende doeleinden, niet verwarren
  • s-maxage — overschrijft max-age voor shared cache, nuttig voor scheiding van browser/CDN-beleid
  • stale-while-revalidate — weergave van verouderde cache met achtergrondupdate voor onmiddellijke UX
  • Aanbeveling — configureer Cache-Control voor elk resourcetype op de server en in de mobiele HTTP-client

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook