All articles · Web Security

HSTS Preload Without Regrets: A Staged Rollout Plan

Cover with the article title next to a shield with a check mark, in green on a dark background

HTTP Strict Transport Security is one of the cheapest security wins on the web: one response header, and browsers stop making plain-HTTP requests to your site. The preload list takes it one step further by baking your domain into the browser itself, so even the very first visit is protected.

It is also one of the few web settings you can’t quickly take back. Once your domain is preloaded with includeSubDomains, every subdomain must work over HTTPS in every major browser, and removing the entry takes months to reach users. This article is a plan for getting there without discovering a broken subdomain the hard way.

What HSTS does, briefly

When a browser receives this header over HTTPS:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

it remembers, for max-age seconds (here two years), that the host must only be contacted over HTTPS. Typed http:// links, old bookmarks and plain-HTTP redirects are upgraded inside the browser before any request leaves the machine. Certificate errors become non-bypassable: the user can’t click through a warning.

includeSubDomains extends the rule to every subdomain. preload is a signal that you consent to being added to the browser preload list.

The weak spot of plain HSTS is the first visit: until the browser has seen the header once, a network attacker can still intercept a plain-HTTP request. The preload list closes that gap, because Chrome, Firefox, Safari and Edge ship with the list built in.

Our HSTS guide covers what our scanner checks: a max-age of at least 180 days, includeSubDomains and preload.

The preload requirements

To be accepted on hstspreload.org, a domain must:

  1. Serve a valid certificate.
  2. Redirect from HTTP to HTTPS on the same host, if it listens on port 80.
  3. Serve all subdomains over HTTPS, in particular www if it has a DNS record.
  4. Send the HSTS header on the base domain, over HTTPS, with:
    • max-age of at least 31536000 (one year),
    • includeSubDomains,
    • preload.
  5. If the HTTPS base domain redirects elsewhere, the redirect response itself must carry the HSTS header.

Requirement 3 is where projects get hurt. The submission form checks your apex and www; it has no way to check printer.office.example.com or the marketing tool someone pointed at go.example.com three years ago.

Step 0: inventory every subdomain

Before you touch the header, build a list of every hostname under your domain that a browser might visit. Sources worth combining:

  • Your DNS zone. Every A, AAAA and CNAME record. Wildcard records deserve special attention.
  • Certificate Transparency logs. Public CT search tools show every certificate ever issued for your names, which often surfaces forgotten hosts.
  • Email and marketing tools. Click-tracking and landing-page services frequently run on a branded subdomain (links., email., go.) via CNAME. Some only offer HTTPS on custom domains as a paid or opt-in feature. This is one of the most common things preload breaks.
  • Internal tools exposed in public DNS: VPN portals, intranets, printers, NAS boxes, old Jenkins servers. If they resolve publicly and a browser on the network visits them by name, HSTS applies.
  • Staging and test hosts, especially ones with self-signed certificates. Under HSTS a certificate warning can’t be clicked through, so a self-signed staging host simply becomes unreachable in the browser.

For each host, write down whether it serves a valid certificate today. Anything that doesn’t is a blocker for includeSubDomains.

Step 1: HSTS on the apex with a short max-age

Start small:

Strict-Transport-Security: max-age=300

Five minutes. If something goes wrong, browsers forget within five minutes. Confirm that every page, redirect and asset on the main host works over HTTPS, that your HTTP-to-HTTPS redirect is a single hop (see HTTPS redirects), and that nothing on the page is loaded over plain HTTP (mixed content).

Step 2: add includeSubDomains, still short

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

Now the rule covers your whole inventory. Visit each subdomain from a browser that has seen the header. Ask the teams who own them to do the same. Anything with a certificate error or an HTTP-only service shows up now, while you can still undo it in five minutes.

Step 3: ramp up max-age

Increase in stages, leaving each step in place long enough for problems to be reported:

Stage max-age Leave it for
1 300 (5 minutes) a day
2 86400 (1 day) a few days
3 604800 (1 week) a week
4 2592000 (30 days) a month
5 63072000 (2 years) permanent

The idea is that each step’s worst case is bounded by its own max-age. If someone discovers a broken subdomain at stage 3, affected browsers recover within a week.

Step 4: add preload and submit

Once a long max-age with includeSubDomains has run without complaints, add preload and submit the domain at hstspreload.org. The site checks the live header and shows any problems. Accepted domains go into the list that ships with the next browser releases, which takes several weeks to reach users.

From this point, the setting is effectively permanent. Removal is possible, but it has to go through the same release cycle in every browser, and users on older browser versions keep the entry until they update. Plan for months, not days.

Common gotchas

  • HSTS sent over HTTP. Browsers ignore the header on plain-HTTP responses. It only counts over HTTPS.
  • Header only on some responses. If HTML gets the header but your redirect responses or error pages don’t, the submission check fails and the protection is patchy. Set it at the load balancer or CDN so every response carries it.
  • Apex redirects straight to https://www without visiting the HTTPS apex. The preload check wants the apex itself to serve the header over HTTPS. Redirect http://example.com → https://example.com → https://www.example.com (or the reverse for an apex-canonical site), so the apex sets the policy. Our www vs non-www guide covers picking one.
  • max-age=0 left over from a test. That actively tells browsers to forget the policy.
  • Separate tools on the same domain, like a help desk or status page run by a vendor, that only support HTTPS once someone flips a setting in their dashboard. Check before, not after.

Should you preload at all?

For most public websites that are fully on HTTPS, yes. The first-visit gap is real on public Wi-Fi, and preloading costs nothing once your inventory is clean.

It’s a harder call if your organization has a long tail of subdomains owned by many teams, or devices you don’t control living under the same domain. In that case, keep HSTS with a long max-age on the hosts you do control, skip includeSubDomains and preload for now, and plan the cleanup as its own project. A well-configured HSTS header without preload is still far better than none.

Whichever you choose, the staged approach is the same: short max-age, wide coverage, then longer max-age, and preload last.

Tags:HSTSHTTPSpreloadTLSsecurity headers