Caching · Response header
Expires
Declares a wall-clock deadline (HTTP-date) for how long the response stays fresh. Includes exact format, 4 production-ready server configs (Apache, Nginx, Express, CDNs), and the deprecation caveats with Cache-Control.
What is Expires?
Expires sets a wall-clock deadline for response freshness. After the given HTTP-date passes, caches should return a stale response — they may revalidate or re-fetch. It's an absolute timestamp, not a relative duration, which means server clock drift directly impacts cache behaviour. For most new deployments, Cache-Control: max-age is preferred because it's relative (no clock dependency) and gives finer control (public/private, s-maxage, must-revalidate).
Typical usage
Set Expires only as a fallback alongside Cache-Control: max-age for legacy CDN compatibility. For static assets with far-future dates (1 year+), consider switching to immutable + Cache-Control: immutable so browsers skip revalidation entirely.
Examples
One-hour freshness
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: max-age=3600Far-future static asset
Expires: Tue, 21 Jul 2027 00:00:00 GMT
Cache-Control: public, max-age=31536000, immutableForce immediate expiry
Expires: 0
Cache-Control: no-cacheDon't cache at all
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-storeHTML <meta> equivalent (legacy)
<meta http-equiv="Expires" content="Wed, 21 Oct 2026 07:28:00 GMT">Common gotchas
1) If both Expires and Cache-Control: max-age are present, max-age wins per RFC 9111. 2) Server clock drift makes absolute dates unreliable — a server 5 minutes behind makes the response look 5 minutes fresher than intended. 3) Expires: 0 is special — it's an invalid date that most browsers treat as 'already expired,' equivalent to Cache-Control: no-cache. 4) Setting Expires to a past date is the old-school way to bust the cache, but no-cache/must-revalidate is more precise for modern browsers. 5) The HTML <meta http-equiv="Expires"> tag is widely ignored by modern browsers and CDNs — always set the real Expires / Cache-Control HTTP response header on the server instead.
Also known as
Also commonly written as: expires header · expires headers · http expires header · html expires · expires header html · meta expires · expires meta tag · http-equiv expires · expires 0. These variants — including plural forms, unhyphenated spellings, and Japanese (ヘッダ) — all refer to the same Expires HTTP header.
Specification
RFC 9111 §5.3
Frequently asked questions
What is the Expires HTTP header?
Expires sets a wall-clock deadline for response freshness. After the given HTTP-date passes, caches should return a stale response — they may revalidate or re-fetch. It's an absolute timestamp, not a relative duration, which means server clock drift directly impacts cache behaviour. For most new deployments, Cache-Control: max-age is preferred because it's relative (no clock dependency) and gives finer control (public/private, s-maxage, must-revalidate).
Is Expires a request or response header?
Expires is a response header — the server sends it to the client. Set Expires only as a fallback alongside Cache-Control: max-age for legacy CDN compatibility. For static assets with far-future dates (1 year+), consider switching to immutable + Cache-Control: immutable so browsers skip revalidation entirely.
What does a Expires header look like?
A typical Expires header looks like: Expires: Thu, 01 Dec 1994 16:00:00 GMT / Cache-Control: max-age=3600 (One-hour freshness).
What are common mistakes with Expires?
1) If both Expires and Cache-Control: max-age are present, max-age wins per RFC 9111. 2) Server clock drift makes absolute dates unreliable — a server 5 minutes behind makes the response look 5 minutes fresher than intended. 3) Expires: 0 is special — it's an invalid date that most browsers treat as 'already expired,' equivalent to Cache-Control: no-cache. 4) Setting Expires to a past date is the old-school way to bust the cache, but no-cache/must-revalidate is more precise for modern browsers. 5) The HTML <meta http-equiv="Expires"> tag is widely ignored by modern browsers and CDNs — always set the real Expires / Cache-Control HTTP response header on the server instead.
Related headers
Cache-Control
Directives that control caching behavior.
Date
When the response was generated.
Age
How many seconds the response has been in a shared cache.
Last-Modified
When the resource was last modified.
If-Modified-Since
Send the resource only if it changed after this date.
ETag
A version identifier for the resource — the backbone of conditional GETs.
Vary
Which request headers cause different cached variants of the response.
Content-Length
The size of the body in bytes.