Expires headers work in conjunction with Cache-Control headers to tell the browser or shared cache how long the content can be served before it needs to be revalidated with the origin web server.  The Expires header can be used in place of the max-age or s-maxage directive in the Cache-Control header.   If an Expires header and a max-age directive both exist in a response, the max-age directive overrides the Expires header.  This is true even if the Expires header is more restrictive. 

A server can send either an Expires header a Cache -Control header or neither, where and how long the content is cached for is influenced by the presence or absence of both of these headers.

Scenario 1: Server sends Expires header but no Cache-Control header

The response below has an explicitly defined expiration date but there are no Cache-Control headers.  This indicates that the image can be cached by both public and private/shared caches

(Status-Line) HTTP/1.1 200 OK
Content-Length 4722
Content-Type image/gif
Date Wed, 08 Oct 2008 10:20:29 GMT
Expires Sun, 17 Jan 2038 19:14:07 GMT
Last-Modified Wed, 07 Jun 2006 23:55:38 GMT

Scenario 2: Server sends Expires header and Cache-Control header

In this response caches are told from the Cache-Control header that only private caches such as browsers can cache the data.  The Expires header is used to specify the length of time the item can be cached for 30 years.  An Expires value this long essentially tells caches that this content never expires. 

(Status-Line)    HTTP/1.1 200 OK
Cache-Control    private
Content-Length    11638
Content-Type    image/png
Date    Wed, 08 Oct 2008 14:52:40 GMT
Expires    Sun, 17 Jan 2038 19:14:07 GMT
Last-Modified    Fri, 20 Jun 2008 23:40:44 GMT

Scenario 3: Server sends Cache-Control header but no Expires  header

In this instance the Cache-Control header is being used to tell both public and private caches to cache the content for 86400 seconds or 24 hours.

(Status-Line)    HTTP/1.1 200 OK
Accept-Ranges    bytes
Cache-Control    max-age=86400
Content-Length    4704
Content-Type    image/jpeg
Date    Wed, 08 Oct 2008 15:02:33 GMT

Scenario 4: Server sends neither Cache-Control header nor Expires header

When neither header is present the content is still considered cacheable however by the time it is received it is already expired.  Content with an immediate expiration is cached however each and every subsequent request will result in a conditional GET being issued to the origin server to validate that the content has not changed.  

(Status-Line) HTTP/1.1 200 OK
Accept-Ranges bytes
Connection Keep-Alive
Content-Length 221
Content-Type Image/gif
Date Fri, 31 Aug 2007 10:27:06 GMT
Last-Modified Fri, 02 Jun 2006 09:46:32 GMT