惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

CSS Wizardry

Front-End’s Missing Metric: The TBT Window Meet Your Users Where They Are with Obs.js Better Browser Caching with No-Vary-Search font-family Doesn’t Fall Back the Way You Think What Is CSS Containment and How Can I Use It? When All You Can Do Is All or Nothing, Do Nothing Obs.js: Context-Aware Web Performance for Everyone Low- and Mid-Tier Mobile for the Real World (2025) The Fastest Site in the Tour de France Making Sense of the Performance Extensibility API Why Do We Have a Cache-Control Request Header? HTML Is Not a Programming Language… Build for the Web, Build on the Web, Build with the Web Licensing Code on CSS Wizardry A Layered Approach to Speculation Rules Designing (and Evolving) a New Web Performance Score Core Web Vitals Colours The Ultimate Contract Templates for Tech Consultants: Protect Your Business and Get Paid Optimising for High Latency Environments Cache Grab: How Much Are You Leaving on the Table? blocking=render: Why would you do that?! Correctly Configure (Pre) Connections The Three Cs: 🤝 Concatenate, 🗜️ Compress, 🗳️ Cache How to Clear Cache and Cookies on a Customer’s Device The Ultimate Low-Quality Image Placeholder Technique Core Web Vitals for Search Engine Optimisation: What Do We Need to Know? The HTTP/1-liness of HTTP/2 In Defence of DOM­Content­Loaded Site-Speed Topography Remapped Why Not document.write()? Speeding Up Async Snippets Critical CSS? Not So Fast! Measure What You Impact, Not What You Influence Optimising Largest Contentful Paint Measuring Web Performance in Mobile Safari Site-Speed Topography Speed Up Google Fonts Real-World Effectiveness of Brotli Performance Budgets, Pragmatically Lazy Pre-Browsing with Prefetch Making Cloud.typography Fast(er) Time to First Byte: What It Is and How to Improve It Self-Host Your Static Assets Tips for Technical Interviews Cache-Control for Civilians Bandwidth or Latency: When to Optimise for Which ITCSS × Skillshare What If? CSS and Network Performance The Three Types of Performance Testing Getting to Know a Legacy Codebase Image Inconsistencies: How and When Browsers Download Images Identifying, Auditing, and Discussing Third Parties My Digital Music Setup Measuring the Hard-to-Measure Finding Dead CSS The Fallacies of Distributed Computing (Applied to Front-End Performance) Ten Years Old Relative Requirements Airplanes and Ashtrays Performance and Resilience: Stress-Testing Third Parties Refactoring Tunnels Little Things I Like to Do with Git Writing Tidy Code Configuring Git and Vim Base64 Encoding & Performance, Part 2: Gathering Data Base64 Encoding & Performance, Part 1: What’s Up with Base64? Code Smells in CSS Revisited Typography for Developers Moving CSS Wizardry onto HTTPS and HTTP/2 Ack for CSS Developers A New Year, a New Focus Preparing Vim for Apple’s Touch Bar Choosing the Correct Average CSS Shorthand Syntax Considered an Anti-Pattern CSS Wizardry Newsletter Nesting Your BEM? Improving Perceived Performance with Multiple Background Images Continue Normalising Your CSS Pure CSS Content Filter Pragmatic, Practical, and Progressive Theming with Custom Properties Refactoring CSS: The Three I’s Speaker’s Checklist: Before and After Your Talk Improving Your CSS with Parker The Importance of !important: Forcing Immutability in CSS Mixins Better for Performance Managing Typography on Large Apps White October Events Workshop Partnership BEMIT: Taking the BEM Naming Convention a Step Further Travelling Like You Want to, When You Have To Contextual Styling: UI Components, Nesting, and Implementation Detail Subtleties with Self-Chained Classes Cyclomatic Complexity: Logic in CSS Immutable CSS Can CSS Be Too Modular? More Transparent UI Code with Namespaces When to use @extend; when to use a mixin The Specificity Graph CSS Wizardry Ltd.: Year 1 in review CSS Guidelines 2.0.0
What Is the Maximum max-age?
Harry Roberts · 2023-10-16 · via CSS Wizardry

(last updated on )

Written by on CSS Wizardry.

Table of Contents

Independent writing is brought to you via my wonderful Supporters.

  1. max-age
  2. immutable
  3. 31536000 Seconds
  4. 2147483648 Seconds
  5. Does It Matter?

Try out the max-age calculator.

If you wanted to cache a file ‘forever’, you’d probably use a Cache-Control header like this:

Cache-Control: max-age=31536000

This instructs any cache that it may store and reuse a response for one year (60 seconds × 60 minutes × 24 hours × 365 days = 31,536,000 seconds). But why one year? Why not 10 years? 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, or 68 years. To find out why, read on!

Need Some Help?

I help companies find and fix site-speed issues. Performance audits, training, consultancy, and more.

max-age

max-age is a Cache-Control directive that instructs a cache that it may store and reuse a response for n seconds 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, we must be also quite confident that it never really changes. After all, a year 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;
}

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;
}

…would have a checksum of 6bb70b2a68a0e28913a05fb3656639b6. 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 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

Traditionally, developers have set ‘forever’ max-age values at 31536000 seconds, which is a year. Why a year, though? A year isn’t forever. Was 31536000 arrived at by agreement? Or is it specified somewhere? RFC 2616 says of the Expires header:

To mark a response as ‘never expires,’ an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year 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-age, which is a Cache-Control directive. Does Cache-Control say anything different?

2147483648 Seconds

It turns out there is a maximum value for max-age, and it’s defined in RFC 9111’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 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 (231) 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 (which is 68 years), 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!) or higher. If the cache can work with it, that’s how long it will store it. If it can’t handle 317 years, it should fall back to 2,147,483,648 seconds, and if it can’t handle that, whatever the biggest value it can handle.

And why 2,147,483,648 seconds?

In a 32-bit system, the largest possible integer that can be represented in binary form is 01111111111111111111111111111111: a zero followed by 31 ones (the first zero is reserved for switching between positive and negative values, so 11111111111111111111111111111111 would be equal to −2,147,483,648).

Need Some Help?

I help companies find and fix site-speed issues. Performance audits, training, consultancy, and more.

Does It Matter?

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 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 31536000s for 2147483648s. It works in all major browsers.

Need a second pair of eyes on your caching strategy? Arrange a performance audit!


Frequently Asked Questions

What is the maximum value for cache-control’s max-age?

Most teams stick to one year, but RFC9111 states caches MUST honour any value up to 2,147,483,648 seconds—68 years—the largest signed 32-bit integer.

Should I swap my 31536000s for 2147483648s?

Maybe, but only for truly immutable, fingerprinted assets. HTML and API responses should keep short or revalidated lifetimes to avoid serving stale data.