HTTP Cache Expiration

The expiration model is the most efficient and straightforward of the two
caching models and should be used whenever possible. When a response is cached
with an expiration, the cache returns it directly without hitting the application
until the cached response expires.

The expiration model can be accomplished using one of two, nearly identical,
HTTP headers: Expires or Cache-Control.

Expiration and Validation

You can of course use both validation and expiration within the same Response.
As expiration wins over validation, you can easily benefit from the best of
both worlds. In other words, by using both expiration and validation, you
can instruct the cache to serve the cached content, while checking back
at some interval (the expiration) to verify that the content is still valid.

An alternative to the Cache-Control header is Expires. There's no advantage
or disadvantage to either: they're just different ways to set expiration caching
on your response.

According to the HTTP specification, "the Expires header field gives
the date/time after which the response is considered stale." The Expires
header can be set with the setExpires()Response method. It takes a
DateTime instance as an argument:

The setExpires() method automatically converts the date to the GMT
timezone as required by the specification.

Note that in HTTP versions before 1.1 the origin server wasn't required to
send the Date header. Consequently, the cache (e.g. the browser) might
need to rely on the local clock to evaluate the Expires header making
the lifetime calculation vulnerable to clock skew. Another limitation
of the Expires header is that the specification states that "HTTP/1.1
servers should not send Expires dates more than one year in the future."

Note

According to RFC 7234 - Caching, the Expires header value is ignored
when the s-maxage or max-age directive of the Cache-Control
header is defined.