HSTS tells a browser to remember that a hostname requires HTTPS. A redirect protects the next step after an HTTP request reaches a server; a remembered HSTS policy upgrades that request before the browser sends it. The operational cost is equally concrete: a certificate outage cannot be worked around by moving visitors back to HTTP.
Exercise: stage one host without covering its subdomains
Use an owned staging hostname, shown here as hsts-lab.example.com, that is not already preloaded or covered by a parent's includeSubDomains policy. Check the parent domain's current headers and preload status first. Otherwise your experiment may inherit a policy that this host cannot undo. Use a dedicated test browser profile and keep production profiles untouched.
First verify a valid certificate, an HTTP-to-HTTPS redirect on this same hostname, renewal monitoring and representative HTTPS routes, including redirects and errors. If a CDN terminates TLS, test its public certificate and responses too. This example assumes an existing HTTPS Apache 2.4 virtual host with mod_headers loaded. Add the following inside that host's port 443 VirtualHost block, with one layer responsible for HSTS:
# First stage: this hostname only, five minutes.
Header onsuccess unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=300"Run apachectl configtest before reloading your service. Keep the port 80 redirect. Do not put HSTS on the HTTP response and assume the browser will trust it: the browser accepts this policy over valid HTTPS.
The durations below are an example rollout plan for a host you can monitor. They are not measurements or a claim that five minutes is sufficient testing:
- Five minutes: serve
max-age=300. Exercise the ordinary page, login or callback routes, downloads and an error response. Monitor TLS failures. - One week: after the short stage is healthy, replace the value with
max-age=604800. Observe for at least the stage duration and include a certificate-renewal rehearsal using your normal renewal tooling. - Thirty days: use
max-age=2592000when monitoring, ownership and renewal recovery are reliable. Wait through this stage before extending further. - Longer retention: decide deliberately whether
max-age=31536000fits your service. Every valid HTTPS response with the header refreshes the expiry from that visit.
Verify the header separately from browser memory
curl -sS -D - -o /dev/null http://hsts-lab.example.com/
curl -sS -D - -o /dev/null https://hsts-lab.example.com/
curl -sS -D - -o /dev/null https://hsts-lab.example.com/missing-test-pageIllustrative expected output: the HTTP response redirects to https://hsts-lab.example.com/. Both HTTPS responses carry exactly one Strict-Transport-Security: max-age=300 at the first stage, even if the missing page returns 404. These are expected values, not results collected from a deployed lab. A missing error-page header often means the CDN or error handler uses a different rule.
To check browser behavior, visit the valid HTTPS URL in your test profile. Open Developer Tools with network logging preserved, then navigate explicitly to the HTTP URL. Look for the browser's internal upgrade to HTTPS; the label varies by browser. Compare with the server's access logs to determine whether an HTTP request actually reached port 80. HTTPS-first browser settings can also upgrade a navigation, so the final HTTPS address alone does not identify HSTS as the cause.
Ordinary curl header checks do not establish browser HSTS memory. Some curl builds support an explicit --hsts cache, which is separate from the browser. Do not use -k to hide a certificate failure during verification.
Rollback while HTTPS still works
For a host-only dynamic policy, replace the header with the following and keep serving valid HTTPS:
Header onsuccess unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=0"Check the public response, then revisit HTTPS in the same test profile so it receives the cancellation. Deleting the header from the server does not delete policies already stored by visitors. A visitor who does not return retains the old policy until its stored expiry. If TLS is broken, that visitor cannot receive the cancellation header until HTTPS is repaired.
A parent's includeSubDomains policy still covers a child that sends max-age=0. Independently remembered child policies can also outlive a change to the parent. Keep an inventory of which hostname set each policy when investigating a rollback.
Subdomains and preload require a separate decision
Only add includeSubDomains after checking all descendants, including internal, delegated, legacy and future names. A working main website is insufficient. Applying it to example.com covers old.example.com as well as deeper names.
The preload service currently recommends ordinary HSTS while advising against preloading as a default. Preload distribution can protect a first visit before a dynamic policy is learned, but it creates a longer commitment. Eligibility includes valid HTTPS, all-subdomain readiness, a same-host HTTP redirect where port 80 is used, and a base-domain policy containing at least a year, includeSubDomains and preload. Merely adding the word does not prove a domain is in browser lists. Removal is a separate request and browser updates can take months to reach users. Neither removing that word nor sending max-age=0 instantly removes an embedded preload entry.
HSTS does not repair mixed content, insecure cookies or application bugs. A successful rollout means you have checked the transport policy and its recovery path, with certificate monitoring still required.