How long should HSTS max-age be?
hsts-max-age-short global
The issue
A short HSTS max-age lets the policy lapse between visits. A visitor who returns after it expires is back on plain HTTP for the first request, where an attacker on the network can stop the upgrade to HTTPS.
The cause is a cautious value from rollout, such as a day or a month, that was never raised.
Scope
max-age applies to the whole hostname. Each HTTPS response that carries the header restarts the timer in the browser. Probeo checks the value on each response it fetches.
How to check you have it
- In probeo: a
max-ageunder 31536000 seconds is recorded ashsts:short-max-age, and no header at all ashsts-missing. - By hand: run
curl -sI https://example.com/and read the number aftermax-age=instrict-transport-security.
The fix
Set max-age to at least 31536000 seconds, one year.
Two years, 63072000, is a common choice. If HSTS is new to the site, start short, at 300 seconds, and raise the value in steps once HTTPS has proved reliable.
Done when: every HTTPS response sends a max-age of at least one year, and the check above comes back clean.
Do not
- Do not use a value below 31536000 seconds in production.
- Do not set a long value before HTTPS has been tested.
- Do not send different values on different paths of the same host.
FAQ
Why not set max-age to maximum possible value?
Extremely long max-age values provide minimal additional security over one or two years. The risk of permanent lockout increases with duration. If HTTPS becomes unsupportable, extremely long max-age requires waiting years for expiry or difficult manual browser clearing. Two years balances strong protection with eventual recovery possibility. Practical considerations favor two years as the upper recommended value.
What happens to users who visit once then return after max-age expires?
Those browsers lose HSTS enforcement after expiry. The next visit allows HTTP connections until a new HSTS header is received over HTTPS. If the user requests HTTP directly, the connection succeeds without upgrade. If HTTP redirects to HTTPS normally, the new HSTS header re-enables enforcement. Long max-age reduces the likelihood of this scenario affecting users with long gaps between visits.
Should max-age increase gradually or jump to final value?
Start with short max-age during initial rollout for quick recovery if issues arise. Use 300 seconds for initial testing. Increase to 86400 after successful validation. Ramp to 2592000 after longer observation. Jump to 31536000 or 63072000 when confidence is high. Gradual increase allows backing out quickly during early stages while moving toward strong protection.
Does max-age affect HTTPS certificate renewal timing?
No. A certificate doesn’t need to outlast max-age; it needs to be renewed before it expires. HSTS raises the stakes, because an expired certificate becomes an error visitors can’t click past. Automate renewal.
Can different pages on the same hostname use different max-age?
Browsers use the most recently seen max-age value for the entire hostname. HSTS does not operate at path level. A response with max-age=63072000 on /login and max-age=31536000 on /about results in whichever value the browser saw most recently applying globally. Consistency across all responses prevents confusion. Configure one max-age value for all paths.
How does max-age interact with preload?
Preload has its own persistence independent of max-age. Domains on the preload list enforce HSTS until removed from browser code updates. Max-age still applies to determine when browsers expire locally learned HSTS for updates or removal. Submission to the preload list requires a max-age of at least 31536000 seconds. Both mechanisms reinforce each other for maximum protection.
Which product detects this
Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.