Last-Modified — is een HTTP-responseheader die de datum en tijd van de laatste wijziging van een bron op de server aangeeft, waardoor de client voorwaardelijke verzoeken via If-Modified-Since kan uitvoeren. Als de bron niet is gewijzigd sinds de opgegeven datum, retourneert de server 304 Not Modified zonder de responsebody te verzenden, wat aanzienlijk bandbreedte bespaart. Volgens RFC 7232 (IETF, 2014) verkorten voorwaardelijke verzoeken met Last-Modified de laadtijd van pagina’s met 30–60% bij herhaalde bezoeken. De header wordt automatisch ondersteund door de meeste HTTP-servers en proxies.
Belangrijkste punten
Last-Modified — is een HTTP-header die behoort tot de groep van voorwaardelijke verzoeken (conditional requests). De server voegt deze toe aan het antwoord op GET of HEAD, met de datum en tijd van de laatste wijziging van de opgevraagde bron in HTTP-date-formaat: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT. De client (browser, mobiele app, proxy) slaat deze datum samen met de gecachte bron op. Bij een herhaald verzoek stuurt de client de header If-Modified-Since met dezelfde datum, en de server vergelijkt deze met de huidige wijzigingstijd van de bron.
Het protocol voor voorwaardelijke verzoeken met Last-Modified is gedefinieerd in RFC 7232 en wordt ondersteund door alle moderne HTTP-servers. Het datumformaat is strikt gereguleerd — alleen GMT (Greenwich Mean Time) zonder tijdzone-aanduiding. De server kan de datum in drie mogelijke formaten retourneren: RFC 1123 (standaard), RFC 850 (verouderd) of ANSI C asctime. In de praktijk gebruiken bijna alle servers het RFC 1123-formaat met een vaste lengte van 29 tekens.
Last-Modified valt in de categorie validatiemechanismen voor caching: het vertelt de client niet of het antwoord gecacht mag worden, maar biedt een hulpmiddel om de actualiteit van een reeds gecachte bron te controleren. Het cachebeleid wordt apart ingesteld via de Cache-Control-header. Volgens onderzoek van Akamai (2025) vermindert de juiste configuratie van Last-Modified samen met Cache-Control de belasting van originservers met tot 70% voor statische content.
De Last-Modified-header werd al gedefinieerd in HTTP/1.0 (RFC 1945, 1996) en was een van de eerste mechanismen voor cachebeheer op het web. Vóór de komst van ETag in HTTP/1.1 was het de enige manier om voorwaardelijke verzoeken uit te voeren. Ondanks zijn leeftijd blijft de header relevant vanwege zijn eenvoud — de server hoeft geen hash van de content te berekenen, het is voldoende om de timestamp van het bestand uit het bestandssysteem of het updated_at-veld uit de database te lezen.
De volledige cyclus omvat drie fasen. Bij het eerste verzoek retourneert de server de bron met de Last-Modified-header en HTTP-status 200 OK. De client cacht het antwoord samen met de datum. Bij een herhaald verzoek stuurt de client de header If-Modified-Since met de opgeslagen datum. De server vergelijkt deze datum met de huidige wijzigingstijd van de bron. Als de bron niet is gewijzigd — wordt 304 Not Modified met een lege body geretourneerd. Indien gewijzigd — 200 OK met nieuwe gegevens en een nieuwe Last-Modified.
// Eerste verzoek — server retourneert bron met datum
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT
[{"id": 1, "name": "Alice"}]
// Herhaald verzoek — client stuurt opgeslagen datum
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT
// Antwoord — gegevens niet gewijzigd
HTTP/1.1 304 Not Modified
Voor mobiele applicaties is Last-Modified vooral nuttig bij gegevenssynchronisatie. De app slaat de datum van de laatste succesvolle update op en stuurt deze naar de server in If-Modified-Since. Als er meer gegevens zijn of deze zijn gewijzigd — retourneert de server de volledige set. Zo niet — 304, en de app gebruikt de lokale kopie. OkHttp en URLSession ondersteunen dit mechanisme automatisch via ingebouwde cachesystemen.
Voor statische bestanden halen Nginx en Apache de datum uit de bestandssysteemattributen — mtime (wijzigingstijd). Voor dynamische content moet de servercode Last-Modified expliciet instellen op basis van bedrijfslogica: het updated_at-veld uit de database, de datum van de laatste commit in Git, de timestamp van de artefactbuild. Als Last-Modified niet expliciet is ingesteld, kan de server de header helemaal niet retourneren en kan de client geen voorwaardelijke verzoeken op basis van datum uitvoeren.
Last-Modified en ETag vervullen een vergelijkbare taak — ze stellen de client in staat de actualiteit van de cache te controleren — maar hebben fundamentele verschillen. Last-Modified gebruikt een tijdstempel, ETag — een unieke versie-ID. Elke benadering heeft scenario’s waarin deze effectiever is, en de aanbeveling van de HTTP-specificatie is om beide headers samen te gebruiken.
| Criterium | Last-Modified | ETag |
|---|---|---|
| Essentie | Datum laatste wijziging | Unieke versie-ID |
| Nauwkeurigheid | Tot seconde | Tot bit (hash) |
| Implementatiecomplexiteit | Laag — automatisch uit bestandssysteem | Gemiddeld — hashberekening vereist |
| Clusterservers | Probleem: mtime kan verschillen per node | Stabiel bijzelfde data op nodes |
| Bereikondersteuning | Geen invloed op Range-verzoeken | Vereist sterke ETag voor bereiken |
| Aanbeveling | Voor statische content en eenvoudige API’s | Voor API’s waar nauwkeurige controle belangrijk is |
Het belangrijkste voordeel van Last-Modified is eenvoud. De server hoeft geen hash van de inhoud te berekenen, wat CPU-bronnen bespaart bij elk verzoek. Voor projecten met hoge belasting die statische bestanden of gegevens met duidelijke tijdstempels leveren, blijft Last-Modified de optimale keuze. ETag biedt daarentegen absolute nauwkeurigheid — wijziging van één letter in een JSON-antwoord verandert de ETag, maar kan de datum ongemoeid laten (als het bestand met dezelfde versie is overschreven).
De specificatie raadt aan beide headers tegelijkertijd te retourneren. De server neemt zowel Last-Modified als ETag op in het 200 OK-antwoord. De client stuurt beide voorwaardelijke headers — If-Modified-Since en If-None-Match. De server controleert eerst ETag (heeft prioriteit), daarna Last-Modified. Als ten minste één een wijziging signaleert — wordt het volledige antwoord geretourneerd. Dit biedt maximale flexibiliteit: ETag zorgt voor nauwkeurigheid, Last-Modified voor een back-upcontrole voor clients die ETag niet ondersteunen.
De configuratie van Last-Modified hangt af van het type server. Voor Nginx en Apache wordt Last-Modified voor statische bestanden automatisch ingesteld op basis van mtime. Voor dynamische applicaties moet de header in de servercode worden ingesteld. Laten we de configuratie op populaire platforms bekijken.
// Express.js — Last-Modified instellen
app.get("/api/users", async (req, res) => {
const updatedAt = await getLastUpdate()
const ifModifiedSince = req.get("If-Modified-Since")
// If-Modified-Since controleren
if (ifModifiedSince && new Date(ifModifiedSince)
>= updatedAt) {
return res.status(304).end()
}
const users = await getUsers()
res.set("Last-Modified", updatedAt.toUTCString())
res.json(users)
})
In het Express.js-voorbeeld haalt de server de datum van de laatste gegevensupdate uit de database, controleert If-Modified-Since van de client en retourneert 304 als de cache actueel is. Als de gegevens zijn gewijzigd — stelt hij een nieuwe Last-Modified in en retourneert het volledige antwoord. toUTCString() converteert de datum naar het vereiste HTTP-formaat. In een productieomgeving is het de moeite waard om caching van updatedAt in Redis toe te voegen om bij elke aanvraag een databasequery te voorkomen.
Nginx stelt automatisch Last-Modified in voor statische bestanden op basis van de laatste wijzigingstijd van het bestand. Uitschakelen of wijzigen van het gedrag kan via de etag-richtlijn (ETag uitschakelen) of via de ngx_http_headers_module. Voor proxyverzoeken naar de backend wordt Last-Modified ongewijzigd doorgegeven vanuit het upstream-antwoord. Belangrijk: als de backend geen Last-Modified retourneert, voegt Nginx deze niet automatisch toe voor dynamische antwoorden.
Last-Modified heeft enkele bekende beperkingen. De belangrijkste is de nauwkeurigheid tot de seconde. Als een bron twee keer binnen één seconde is gewijzigd, kan de client de nieuwe versie missen. In de praktijk is dit een zeldzaam scenario, maar voor updates met hoge frequentie (koersenfeed, chats) wordt ETag aanbevolen. De tweede beperking is het clusteringsprobleem: op verschillende servers kan een bestand een andere mtime hebben vanwege kopiëren of implementatie, waardoor Last-Modified inconsistent wordt.
De derde beperking — verwerking van If-Modified-Since met seconde-nauwkeurigheid kan leiden tot overbodige verzoeken bij frequente polling van de server. Als de client elke 500 ms een If-Modified-Since stuurt, retourneert de server elke keer 200 OK, omdat de datum niet is gewijzigd, maar de bron is in feite al geüpdatet. De oplossing is combinatie met ETag: ETag vangt de wijziging binnen een seconde op, terwijl Last-Modified als back-up blijft.
Het vierde probleem — Last-Modified maakt geen onderscheid tussen verschillende versies van dezelfde bron met dezelfde datum. Als een bestand is hersteld uit een back-up en de mtime komt overeen met het origineel, merkt de client niet dat de inhoud is gewijzigd. ETag lost dit probleem op: de inhoudshash verandert gegarandeerd bij elke gegevenswijziging, ongeacht de tijdstempel. Gebruik voor kritieke gegevens altijd beide headers.
Veelgestelde vragen
Alleen GMT (Greenwich Mean Time) in RFC 1123-formaat: dag van de week, datum, maand, jaar, uren:minuten:seconden. Voorbeeld: Wed, 02 Jul 2025 14:30:00 GMT. Tijdzone is altijd GMT, andere formaten zijn niet toegestaan.
Technisch gezien wel, maar dit schendt RFC 7232. Als de server een datum in de toekomst retourneert, zullen clients de bron pas updaten wanneer die datum aanbreekt. Een dergelijke configuratie wordt als een fout beschouwd — de datum moet in het verleden of heden liggen.
Nee, voorwaardelijke If-Modified-Since-verzoeken werken alleen met GET en HEAD. POST-verzoeken worden niet gecacht en gebruiken geen datumvalidatie. Gebruik voor het controleren van de actualiteit van gegevens bij POST ETag of aangepaste mechanismen.
Cache-Control bepaalt het cachebeleid (maximale bewaartijd, wie mag cachen), terwijl Last-Modified het validatiemechanisme voor verlopen cache is. Na het verlopen van max-age stuurt de client If-Modified-Since om de actualiteit te controleren.
Controleer of de server de header uit de actuele bron instelt — database, bestandssysteem of API. Voor dynamische antwoorden, zorg ervoor dat u expliciet res.setHeader(„Last-Modified”, ...) aanroept in de handlercode.
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