Adding Security Headers Globally with Cloudflare Workers
Learn how to use Cloudflare Workers to inject security headers such as HSTS globally at the edge, with a ready‑to‑run example, deployment steps, and notes on limits and verification.
26 Apr 2026, 12:19 UTC

Problem: injecting headers without touching the origin
Many teams need to enforce security policies such as Strict-Transport-Security (HSTS) or custom logging across all hostnames served by a domain. Doing this in the application layer requires code changes, redeploys, and coordination with every service that sits behind the domain. If the origin is slow to update or runs on a heterogeneous stack, the header can be missing for a noticeable period, leaving users exposed.
Thesis: Cloudflare Workers let you inject or modify headers at the edge, centrally and with low latency
A Worker is a lightweight JavaScript service that runs in Cloudflare’s V8 isolates on every data center. It intercepts the fetch event, can read or modify request/response objects, and then forwards the traffic to the origin. Because the code executes close to the client, the added latency is typically under a millisecond, and the rollout is instantaneous once the Worker is published.
Writing a simple header‑injector Worker
The following script adds an HSTS header with a one‑year max‑age and includes the includeSubDomains directive. It also logs the request path to the console (visible via wrangler tail or the dashboard logs).
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
// Log the path for debugging
console.log(`Request path: ${new URL(request.pathname).pathname}`)
// Fetch the original response from the origin
const response = await fetch(request)
// Clone the response so we can modify headers
const modified = new Response(response.body, response)
modified.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
return modified
}
Save this as src/index.js in a new Wrangler project.
Deploying and testing the Worker
- Initialize the project (run in a terminal with a Cloudflare API token that has
Workers Scriptsedit permission):wrangler init hsts-worker --type=javascript cd hsts-worker - Add the script – replace the generated
src/index.jswith the code above. - Preview locally – start the dev server and make a request to
http://localhost:8787:
In another terminal, run:wrangler dev
You should see thecurl -I http://localhost:8787strict-transport-securityheader in the response. - Publish to the edge – when the preview works, publish the Worker to your zone:
This creates a route pattern (e.g.,wrangler publishexample.com/*) that you configure in the Cloudflare dashboard under **Workers → Triggers**. - Verify in production – after the route is active, check a real hostname:
Look for the headercurl -I https://example.comstrict-transport-security: max-age=31536000; includeSubDomains.
Trade‑offs and limitations
- Free‑tier limits – Workers on the free plan are capped at 100 000 requests per day and 50 ms of CPU time per request. The header‑injector script uses well under 1 ms, but if you add expensive logic (e.g., large JSON parsing, external API calls) you may hit the CPU limit and see requests throttled or served with a 1102 error.
- Debugging workflow –
console.logoutput does not appear in browser developer tools. You must rely on the Cloudflare dashboard logs or runwrangler tailto see debug messages while developing. - Atomicity – Because the Worker runs before the origin, any error in the script (e.g., an exception) will generate a 1101 Worker error response, bypassing the origin entirely. Test thoroughly in
wrangler devbefore publishing.
Actionable closing
Start with a minimal header‑injector like the one above, monitor the Requests and Average CPU Time metrics in the Workers dashboard, and iterate using wrangler dev for fast feedback. If your traffic approaches the free‑tier thresholds, consider upgrading to a paid Workers plan or offloading heavier computation to Workers KV or the origin. This approach gives you a centralized, low‑latency way to enforce security headers without touching any application code.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.