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 — 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.
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 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.
| Directive | Betekenis | Voorbeeld |
|---|---|---|
| max-age | Levensduur in seconden vanaf antwoordmoment | max-age=3600 — 1 uur |
| s-maxage | max-age voor shared cache (proxy, CDN) | s-maxage=86400 — 1 dag voor CDN |
| public | Staat caching voor iedereen toe (inclusief proxy) | public, max-age=3600 |
| private | Staat cache alleen toe voor browser/app | private, max-age=600 |
| no-cache | Niet gebruiken zonder controle (304 verplicht) | no-cache |
| no-store | Caching volledig verbieden | no-store |
| must-revalidate | Na max-age verplicht controleren bij origin | max-age=3600, must-revalidate |
| immutable | Resource 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.
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.
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: 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.
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)).
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.
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.
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.
| Resourcetype | Cache-Control | Toelichting |
|---|---|---|
| Versiebeheerde statische bestanden | public, max-age=31536000, immutable | 1 jaar, bestanden veranderen niet (hash in URL) |
| Niet-versiebeheerde statische bestanden | public, max-age=86400, must-revalidate | 1 dag met verplichte controle daarna |
| API: referentiegegevens | public, max-age=600, stale-while-revalidate=60 | 10 minuten cache + 1 minuut stale |
| API: gebruikersgegevens | private, max-age=60 | 1 minuut, alleen voor specifieke gebruiker |
| API: gevoelige gegevens | no-store | Caching volledig verbieden |
| HTML-pagina’s | no-cache, must-revalidate | Controle 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.
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
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.
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.
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.
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.
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
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.
Lees ook