Every number on this page was measured, not estimated. Unless a table says otherwise, the machine was an Apple M2 Max, 32 GB RAM, macOS 26.6.2. Nothing here is a comparison against another tool.
The fixture behind most of it is next16_framework_runtime: 185 KB of the framework runtime a real Next.js 16 build ships. It is one already-minified production bundle, which is the shape AfterPack actually runs on.
Build time
Measured on 2026-08-31, on the machine above.
| What ran | Input | Time | Throughput |
|---|---|---|---|
| The npm package, on the 185 KB bundle | 185 KB | 225 ms | 0.81 MB/s |
| The engine on its own, same bundle | 185 KB | 210 ms | 0.86 MB/s |
| The npm package, on a 490 KB multi-file build | 490 KB | 615 ms | 0.78 MB/s |
The npm row is the one to plan against. It is the published package doing the work the way a plugin or npx afterpack@latest does it, so it includes the cost of getting your code into the engine and back out. The engine row is the same work with that cost removed, and the 15 ms between them is what the packaging adds.
Peak memory on the engine row was 41.7 MB above baseline for a single 185 KB file. The 490 KB multi-file run held 310 MB at its high-water mark.
Obfuscation is a post-build step, so this time is added to your build, not to your users' page loads. A 490 KB build in about six tenths of a second is the shape of the cost.
The wasm build
@afterpack/wasm is the same engine compiled to WebAssembly, for a Cloudflare Worker, for Node, and for the playground on this site.
| Measure | Value |
|---|---|
| Time on the 185 KB bundle, in Node | 431 ms |
| CI budget on that fixture | 600 ms |
| Download, raw | 4.65 MiB |
| Download, gzipped | 1.41 MiB |
The budget is enforced: a CI check runs the engine five times on that fixture at complexity 8 with the Protection Map on, and fails the build if the median passes 600 ms.
Wasm costs about twice what the native build costs, and that is a deliberate trade the other way round: an earlier build optimised for size came out 39% smaller gzipped and 2.1x slower, which pushed a real 66-file build past the cloud engine's deadline. Speed won.
The download happens once per Worker isolate or per browser tab, not once per build.
A laptop core and a Worker isolate are not the same machine. An isolate has less CPU, a colder cache, and a per-request CPU limit, so the same input takes longer there than this table says. Measure on the platform you will run on before you size a budget against these numbers.
Output size
Obfuscation adds bytes. Measured across the fixture set, per preset, on gzipped output against the same file minified:
| Preset | Gzipped output multiplier |
|---|---|
minify | 1.32x to 1.41x |
light | 1.92x to 2.39x |
medium | 1.61x to 2.70x |
hard | 2.10x to 3.31x |
extreme | 2.91x to 4.37x |
Each range is the spread across the fixtures, not a confidence interval. medium overlaps light because the two presets respond differently to different code shapes.
This is a different measurement from the inflation.max budget on Presets, which caps raw bytes against your input. Compare a number to the budget only when both are measured the same way.
Small files come out proportionally larger than any of these, because every output carries the engine's fixed runtime overhead. Read a ratio on a real bundle.
Next
- Presets: the size budget each preset sets, and what raising one buys.
- Build & CI: where the step belongs in a pipeline.
- Cloudflare Workers: running the wasm build in an isolate.
- Playground: the wasm build, running in your browser, timing itself.