Skip to content
Cutting a 6.1 MB Worker bundle down to 2.3 MB
article2 min read2.9K viewsJul 16, 2026

Cutting a 6.1 MB Worker bundle down to 2.3 MB

The 3 MB limit is not a suggestion, and your dependency graph does not care about your deadline.

Diego Alvarez
Diego Alvarez@diegoalvarez

July 16, 2026 · 2 min read

2.9K views4 comments

Our deploy started failing with Script startup exceeded CPU time limit and, a week later, a hard size rejection. Here is the actual breakdown of where 3.8 MB went, in the order we found it, because the order matters — the first two took an afternoon and got us most of the way.

1. Look at the bundle before guessing (−1.9 MB)

npx wrangler deploy --dry-run --outdir dist then run the output through esbuild's metafile analyser. Two findings: a date library pulling in every locale, and an icon package where a single named import dragged in the full set because the package had no sideEffects: false. Swapping to per-icon imports was a one-line change worth 1.1 MB on its own.

2. Node polyfills you did not ask for (−780 KB)

One transitive dependency imported crypto, which pulled a browserify shim into the graph. The Workers runtime has crypto natively via nodejs_compat. Adding the compat flag and removing the shim was pure deletion.

3. Move the big, rare things off the hot path (−1.1 MB)

A syntax highlighter and a markdown pipeline were in the Worker because two routes needed them. They are now a separate Worker behind a service binding, called by those two routes only. The main Worker got smaller and its cold start went from 38ms to 11ms.

What I would do differently

Put the size check in CI on day one. We added a step that fails the build over 2.5 MB, which leaves headroom before the real limit. Every regression since has been caught in the PR that caused it, by the person who caused it, which is roughly a hundred times cheaper than finding it during a release.

Written by

Diego Alvarez

Diego Alvarez

Platform and DevOps. I run our edge: Cloudflare Workers, KV, R2, and the CI that ships to them. Most of my week is spent shaving kilobytes off a Worker bundle and explaining that eventual consistency is a feature you have to design around, not a bug you can retry your way out of.

4 Comments

Sign in to join the discussion

Lena Fischer
Lena Fischer@lenafischer2mo ago

The icon package one bites everybody. Per-icon imports plus sideEffects: false, and then a lint rule banning the barrel import so it cannot come back in six months when someone copies an old file.

0
Diego Alvarez
Diego Alvarez@diegoalvarez2mo ago

Adding the lint rule. We caught that regression twice more before anyone noticed it was the same regression.

0
Sana Qureshi
Sana Qureshi@sanaqureshi2mo ago

Moving the big rare things behind a service binding is the same shape as putting a reranker behind its own endpoint: the cheap path stays cheap. What did the extra hop cost you on the two routes that pay it?

0
Diego Alvarez
Diego Alvarez@diegoalvarez2mo ago

About 8ms at p50 for the binding hop. Those two routes could afford it — one is an export, one is an admin preview. On the hot path I would have said no and eaten the bundle size instead.

0