Invite-only beta · 9 free places left · Managed hosting on AWS

AceMedia HostTalk to us

PERFORMANCE · 28 OCTOBER 2026

Moving assets to a CDN? Keep your Web Workers at home

Redirecting static files to a media host is an easy speed win, but browsers refuse a Web Worker that redirects to another origin. How to spot it and what to keep at home.

Moving static files to a CDN or a separate media host is one of the easiest speed wins there is. A common way to do it is a redirect: requests for /assets/... on your site get a 302 to the same path on the media host, and the browser follows it. Images, stylesheets and ordinary scripts carry on working.

When I made exactly that change on a site I run, everything looked fine. The page loaded, the styles were there, images were faster. One feature had quietly stopped working: a search panel that did its work in a Web Worker. No error on screen, just nothing happening.

Why workers break on a redirect

Browsers hold Web Workers to a stricter rule than ordinary scripts. A worker script must come from the same origin as the page, and that includes where it ends up after redirects. If new Worker('/assets/search-worker.js') gets a 302 to another host, the browser refuses to start the worker. An ordinary <script> tag following the same redirect is fine, which is why the rest of the page kept working.

Two related things fail the same way:

  • Module workers and their imports. A module worker that imports ./search-index.js resolves that import against the worker's final URL. Through a redirect, the import base, the origin check and any CORS requirement can all go wrong.
  • JSON the worker fetches. If the worker loads /assets/data/index.json and that redirects cross-origin, it now needs CORS headers it never needed before.

How to spot it

The browser console tells you, if you look. In Chrome you will see a SecurityError along the lines of "Script at ... cannot be accessed from origin ...". Firefox reports a similar security error when constructing the worker. Nothing appears on the page itself.

From the command line, a bare request without following redirects shows the cause:

curl -sI https://example.com/assets/search-worker.js | head -5
# HTTP/2 302
# location: https://media.example.com/assets/search-worker.js

Run the same check for every file a worker loads: the worker script, each module it imports, and any data it fetches. Any 3xx response pointing at another host is a problem.

A quick way to find them all is to search your code for the places workers are created and the URLs they use:

grep -rnE "new (Shared)?Worker\(|importScripts\(|serviceWorker\.register\(" assets/ src/

Service workers have the same same-origin rule, and a broken one can be harder to notice because the old registration may keep running for a while.

The fix

Keep the files a worker needs on the page's own origin, and let everything else go to the CDN. In practice:

FileWhere it should live
Images, fonts, ordinary stylesheets and scriptsMedia host or CDN is fine
Worker and service worker scriptsThe page's own origin
Modules imported by a workerThe page's own origin
JSON or data fetched by a workerThe page's own origin, or a host with correct CORS headers

I moved those files to a path the redirect does not cover and updated the references. If you redirect with a web server rule, an exception before the redirect also works. In nginx:

location ^~ /assets/workers/ {
    try_files $uri =404;
}
location ^~ /assets/ {
    return 302 https://media.example.com$request_uri;
}

Two follow-ups are easy to forget:

  • Bump the cache-busting version on the worker URL and its imports (search-worker.js?v=12, or a new hashed filename). Browsers may otherwise keep using a cached redirect.
  • Mind long caches on JSON. If your data files are served with a year-long Cache-Control, moving them without a version change means visitors keep the old copy, or the old redirect, for a very long time. Give data files a versioned name or a shorter cache.

A related gotcha: caching the wrong copy

The other surprise from the same move had nothing to do with workers. I uploaded a new file and requested it through the CDN to check it, about a minute before the publishing step had finished switching the site over. The edge cached what it got at that moment, which was the old response, and kept serving it after the switch.

If you fetch a brand new file through a CDN before your publisher has made it live, the edge may cache the pre-switch copy, including a 404 or a redirect. Either purge that URL after the switch, or wait until publishing has fully finished before you test. Check with a header such as cf-cache-status or age that you are seeing a fresh copy.

A checklist for moving assets

  1. List every worker, service worker, worklet and module import on the site.
  2. Exclude those files, and the data they fetch, from the redirect.
  3. Bump their versions so old cached responses are not reused.
  4. Test with the console open, and check each worker URL with a bare curl -I.
  5. Purge the CDN, or wait, before testing new files through it.

Further reading: MDN on the Worker constructor and its same-origin rule.

More hosting tipsTalk about your hosting

INVITE-ONLY BETA

Tell us about your site.

Nine free hosting beta invites remain for open-source projects, charities, community organisations and other public-benefit work. Tell us what you’re building; we’ll review the fit and reply personally. Fields marked * are required.

Please do not send passwords or private customer data. We’ll use these details to reply. Privacy notice.

Prefer email? Write to [email protected].