What Is the Maximum max-age? – Harry Roberts – Web Performance Consultant

By admin
What Is the Maximum max-age?

Written by

Harry Roberts
PERSON

on CSS Wizardry.

If you wanted to cache a file ‘forever’, you’d probably use a

Cache-Control
PRODUCT

header like this:

Cache-Control: max-age=31536000

This instructs any cache that it may store and reuse a response for

one year
DATE

(

60 seconds ×
TIME


60 minutes × 24 hours
TIME

× 365 days =

31,536,000 seconds
TIME

). But why

one year
DATE

? Why not

10 years
DATE

? Why not max-age=forever ? Why not max-age=∞ ?!

I wondered the same. Let’s find out together.

Like spoilers? See the answer. It’s

2147483648 seconds
TIME

, or

68 years
DATE

. To find out why, read on!


max
PERSON

-age


max
PERSON

-age is a

Cache-Control
ORG

directive that instructs a cache that it may store and reuse a response for

n seconds
GPE

from the point at which it entered the cache in question. Once that time has elapsed, the cache should either revalidate the file with the origin server, or do whatever any additional directives may have instructed it to do. But why might we want to have a max-age that equates to forever?

immutable

If we’re confident that we can cache a file for

a year
DATE

, we must be also quite confident that it never really changes. After all,

a year
DATE

is a very long time in internet timescales. If we have this degree of confidence that a file won’t change, we can cache the file immutably.

immutable is a relatively new directive that effectively makes a contract with the browser in which we as developers tell the browser: this file will never, ever change, ever; please don’t bother coming back to the server to check for updates .

Let’s say we have a simple source CSS file called button.css . Its content is as follows:

.c-btn { background-color : #

C0FFEE
GPE

; }

Once our build system has completed, it will fingerprint the file and export it with a unique hash, or fingerprint, in its filename. The MD5 checksum for this file is 7fda1016c4f1eaafc5a4e50a58308b79 , so we’d probably end up with a file named button.7fda1016.css .

If we change the colour of the button, the next time we roll a release, the build step will do its thing and now, the following content:

.c-btn { background-color : #

BADA55
MONEY

; }

…would have a checksum of

6bb70b2a68a0e28913a05fb3656639b6
CARDINAL

. In that case, we’d call the new file button.6bb70b2a.css .

Notice how the content of the original file button.7fda1016.css hasn’t changed; button.7fda1016.css has ceased to exist entirely, and is replaced by a whole new file called button.6bb70b2a.css .


Fingerprinted
PERSON

files never change—they get replaced. This means we can safely cache any fingerprinted file for, well, forever.

But how long is forever?!


31536000 Seconds
TIME

Traditionally, developers have set ‘forever’ max-age values at

31536000 seconds
TIME

, which is

a year
DATE

. Why a year, though? A year isn’t forever. Was

31536000
CARDINAL

arrived at by agreement? Or is it specified somewhere? RFC

2616
CARDINAL

says of the Expires header:

To mark a response as “never expires,” an origin server sends an Expires date

approximately one year
DATE

from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates

more than one year
DATE

in the future.

Historically—very historically—caching was bound to approximately one year from the time the response is sent . This restriction was introduced by the long defunct Expires header, and we’re talking about

max
PERSON

-age , which is a

Cache-Control
ORG

directive. Does

Cache-Control
ORG

say anything different?


2147483648 Seconds
TIME

It turns out there is a maximum value for max-age , and it’s defined in RFC

9111
PERSON

’s delta-seconds :

A recipient parsing a delta-seconds value and converting it to binary form ought to use an arithmetic type of

at least 31
CARDINAL

bits of non-negative integer range. If a cache receives a delta-seconds value greater than the greatest integer it can represent, or if any of its subsequent calculations overflows, the cache MUST consider the value to be

2147483648
CARDINAL

(

231
CARDINAL

) or the greatest positive integer it can conveniently represent.

The spec says caches should accept a maximum max-age value of whatever-it’s-been-told, falling back to

2,147,483,648 seconds
TIME

(which is

68 years
DATE

), or failing that, falling back to as-long-as-it-possibly-can. This wording means that, technically, there isn’t a maximum as long as the cache understands the value you passed it. Theoretically, you could set a max-age=9999999999 (that’s

317 years
DATE

!) or higher. If the cache can work with it, that’s how long it will store it. If it can’t handle

317 years
DATE

, it should fall back to

2,147,483,648 seconds
TIME

, and if it can’t handle that, whatever the biggest value it can handle.

And why

2,147,483,648 seconds
TIME

?

In a

32
CARDINAL

-bit system, the largest possible integer that can be represented in binary form is

01111111111111111111111111111111
ORG

: a

zero
CARDINAL

followed by

31
CARDINAL

ones (the

first
ORDINAL

zero is reserved for switching between positive and negative values, so 11111111111111111111111111111111 would be equal to

-2,147,483,648
PERSON

).

Does It

Matter
PERSON

?

Honestly, no.

It’s unlikely that a year would ever be insufficient, and it’s also unlikely that any cache would store a file for that long anyway: browsers periodically empty their cache as part of their general housekeeping, so even files that have been stored for

a year
DATE

might not actually make it that long.

This post was mostly an exercise in curiosity. But, if you wanted to, you could go ahead and swap all of your

31536000
CARDINAL

s for

2147483648
CARDINAL

s. It works in all major browsers.

Did this help? We can do way more!