Back to Help Center
SECURITY September 11, 2026 · 8 min read

How to Add the HSTS Header Safely (Without Locking Yourself Out)

HSTS is a one-way street — set it and users' browsers remember for up to 2 years. Stage max-age carefully and audit subdomains before enabling includeSubDomains.

HSTS is powerful and unforgiving. Once a browser caches the policy, it enforces HTTPS-only for the max-age duration — no way to override until it expires. Deploy in stages.

Prerequisites

  • HTTPS working reliably on your domain (valid cert, no mixed-content issues)
  • If you plan to use includeSubDomains: every subdomain also serves valid HTTPS
  • Access to your web server config, CDN, or reverse proxy

Stage 1 — Verify HTTPS Is Solid

Before HSTS, confirm:

  • Every path on your domain serves valid HTTPS
  • Every subdomain used in production serves valid HTTPS
  • No hardcoded HTTP references in your app, in emails, or in third-party integrations
  • Cert renewal automation works (see how to renew Let’s Encrypt)

Check with the SSL certificate checker.

Stage 2 — Short max-age (Test)

Start with a low max-age:

Strict-Transport-Security: max-age=300
  • 300 seconds = 5 minutes of enforcement
  • If something breaks, browsers un-cache within minutes

Deploy this for 24-48 hours. Verify:

  • HTTPS still works everywhere
  • No user reports of “site broken”

Stage 3 — Medium max-age (One Week)

Bump to:

Strict-Transport-Security: max-age=604800
  • 604800 seconds = 7 days
  • Any breakage now takes 7 days to expire for cached users

Wait a week. Watch for issues.

Stage 4 — Full max-age (One Year+)

If Stage 3 is clean:

Strict-Transport-Security: max-age=31536000
  • 31536000 seconds = 1 year
  • Google’s recommended baseline

Stage 5 — includeSubDomains (Optional)

Only do this after auditing every subdomain. Once enabled and cached, every subdomain in scope is HTTPS-only — no override.

Strict-Transport-Security: max-age=31536000; includeSubDomains

Common gotcha: a legacy dev.yourdomain.com or internal intranet.yourdomain.com that serves HTTP. includeSubDomains breaks it for every user who’s already cached the policy.

Stage 6 — Preload (Optional)

For HSTS Preload — Chrome/Firefox/Safari/Edge ship a hard-coded list of HSTS-enforced domains:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 (2 years) — required by the preload list
  • Submit at hstspreload.org

Preloaded means every visitor gets HSTS enforcement from the very first visit. It’s also very hard to remove — plan for permanence.

Verification

After each stage, verify with the security headers checker. Expected: HSTS header present with the correct max-age.

Test the browser’s cached policy: navigate to chrome://net-internals/#hsts (Chrome) or about:config → security.stricttransportsecurity (Firefox).

Common Miss

  • Jumping straight to max-age=31536000; includeSubDomains; preload on day one — cached for years, subdomain breakage lasts forever
  • Enabling includeSubDomains when internal subdomains still serve HTTP — breaks internal tools
  • Setting max-age=0 to disable — cached users keep the policy until expiry; you can’t force flush
  • Preloading and later needing to remove — the removal process takes months and is not guaranteed

Follow up with how to write a Content Security Policy for the next layer.

Check the HSTS glossary entry, read the HTTP security headers explainer, and see how to write a Content Security Policy.