What’s the difference between Expires
and Cache-Control
headers?
7 Answers
Cache-Control
was introduced in HTTP/1.1 and offers more options than Expires
. They can be used to accomplish the same thing but the data value for Expires
is an HTTP date whereas Cache-Control
max-age lets you specify a relative amount of time so you could specify "X hours after the page was requested".
HTML Cache control is a very similar question and has a good link to a caching tutorial that should answer most of your questions (e.g., http://www.mnot.net/cache_docs/#EXPIRES). To sum up though, Expires
is recommended for static resources like images and Cache-Control
when you need more control over how caching is done.
-
11It's worth commenting that cache-control is what all browsers will use, but it's useful to specify both headers just in case there are old proxies in the way. – Nacho Coloma Sep 17 '12 at 14:33
-
3Use the service http://redbot.org/ (also by [Mark Nottingham](http://stackoverflow.com/users/152646/mark-nottingham), who has written the caching article referenced in the answer above) to check for correct usage of caching headers. – daxim Mar 06 '13 at 14:35
-
47Furthermore: "When both Cache-Control and Expires are present, Cache-Control takes precedence." -- [mnot.net/cache_docs/](http://www.mnot.net/cache_docs/) – KFunk Aug 12 '14 at 23:02
If you are using a CDN (Cloud Delivery Network) I recommend to use Cache-Control with a max-age time in seconds. For example Cache-Control: max-age=604800. This prevents request-peaks to your origin-server: With "Expires Wed, 30 Oct 20xx 04:37:07 GMT" all browsers will request you at the same time.

- 495
- 4
- 2
-
28Apache (and probably many servers) usually set the expiration date using the time at which the file was requested + the timeout you specify. As this date is using seconds, your scenario is very unlikely and the behavior is the same as ```cache-control```. So I don't see why there would be requests peaks when using ```Expires:``` – hilnius May 27 '15 at 12:20
According to this Google Developers article, HTTP Caching:
Cache-Control header was defined as part of the HTTP/1.1 specification and supersedes previous headers (e.g. Expires) used to define response caching policies. All modern browsers support Cache-Control, hence that is all we will need.

- 19,704
- 14
- 78
- 96
-
3Not only do all modern browsers support it - they also should, as it is in the spec: "If a response includes both an Expires header and a max-age directive, the max-age directive overrides the Expires header, even if the Expires header is more restrictive" [https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html] – rosell.dk Jan 04 '19 at 09:37
Cache-Control was defined in HTTP/1.1, tells all caching mechanisms from server to client whether they may cache this object. It is measured in seconds: Cache-Control: max-age=3600
.
The Expires
header field gives the date/time after which the response is considered stale. The Expires value is an HTTP-date timestamp: Expires: Tue, 18 Jul 2017 16:07:23 GMT
.
If a response includes a Cache-Control
field with the max-age
directive, a recipient MUST ignore the Expires
field.

- 7,928
- 1
- 20
- 24
Heroku devcenter has an excellent article on this subject.
Quoting from it,
While the Cache-Control header turns on client-side caching and sets the max-age of a resource, the Expires header is used to specify a specific point in time the resource is no longer valid.

- 10,032
- 6
- 34
- 48

- 5,023
- 1
- 34
- 27
-
Downvoted since this answer implies that the two headers are complementary. Cache-Control with a max-age directive will cancel the effect of Expires. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires – StayCool Apr 04 '23 at 04:52
Except for the private/public options of CC, I can't see any difference. When using Expires like "access plus 1 year/month/week/day", it works in exactly the same way as CC does.

- 11
- 4
-
Would you care to explain the downvote ? I did some extensive testing in Chrome, Safari, and Firefox. Cache Control has some options which are not available when using expires, but for all practical purposes, both work in exactly the same way. – Rob Mar 10 '19 at 17:51
If you are still interested, I leave this recommendation directly from google's boys. https://developers.google.com/speed/docs/insights/LeverageBrowserCaching They prefer Expires before than Cache-Control

- 586
- 6
- 14

- 171
- 1
- 11
-
Are you sure they prefer Expires over Cache-Control? I read the override is the other way around, at least for Firefox. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires – Cwista Mar 30 '18 at 12:32
-
Currently, that page mentions "Deprecated. This page was written for version 4 of the PageSpeed Insights API, which is deprecated and will be shut down in May 2019. Version 5 is the latest and provides both real-world data from the Chrome User Experience Report and lab data from Lighthouse." – Jochem Schulenklopper Mar 08 '19 at 09:29