Plate 91
tinypool vs piscina: 5.4 KB vs 10 KB Gzip
Aditya Challa4 min read
I bundled the two Node worker-pool libraries on this box: tinypool 2.2.0 came out at 5,385 bytes gzip, while piscina 5.3.2 came out at 9,994 bytes. On 2,000 tiny CPU tasks across 4 threads, tinypool medians landed around 25–27 ms versus about 29–37 ms for piscina.
Short answer: pick tinypool when you want the smaller Vitest-family pool and slightly cheaper task dispatch on this kind of workload. Keep piscina when you need its TransferList / move helpers and the broader Node-foundation worker API surface. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 02:22 IST.
- Versions: tinypool 2.2.0, piscina 5.3.2, Node 22.20.0, esbuild 0.28.2 node ESM minify + gzip -9.
- Inputs: shared worker module that sums a 5,000-iteration loop. Speed: 2,000 parallel pool.run calls, min/maxThreads=4, median of 9 rounds, two full order-reversed runs. Scripts in /workspace/bench-tinypool-piscina/.
- Findings: tinypool 17,087/5,385 B vs piscina 35,571/9,994 B. Medians (ms for 2k tasks): run-file1 tinypool 25.804 / 25.020 vs piscina 36.542 / 29.542; run-file2 tinypool 26.996 / 25.425 vs piscina 31.161 / 30.914. Result parity matched (4950). Disk ~50 KB vs ~425 KB.
- One surprise: piscina's first warm round after a tinypool run was often the slowest sample in that block; medians still favored tinypool after order reversal.
- Not tested: TransferList / ArrayBuffer move paths, AbortSignal cancellation under load, Windows, Deno/Bun, or Vitest's internal tinypool wiring beyond importing the library.
How much smaller is tinypool?
| Build (esbuild node minify) | Minified | gzip -9 |
|---|---|---|
| tinypool | 17,087 B | 5,385 B |
| piscina | 35,571 B | 9,994 B |
About 1.9× smaller gzip for tinypool. Track tooling cost the same way as size-limit vs bundlesize. If your pool sits next to a test runner decision, see bun test vs Vitest and Jest vs Vitest.
Does task dispatch speed matter?
| 2,000 tasks × 4 threads (median of 9, 2 order-reversed runs, ms) | tinypool | piscina |
|---|---|---|
| Order tinypool then piscina (file 1 / file 2) | 25.804 / 26.996 | 36.542 / 31.161 |
| Order piscina then tinypool (file 1 / file 2) | 25.020 / 25.425 | 29.542 / 30.914 |
tinypool stayed ahead on every median pair on this box. The absolute gap is still small next to real worker compute. Shell-out helpers in a nearby lane sit next to tinyexec vs execa. Coverage tooling that often shares the same monorepo decision shows up in c8 vs nyc.
Do the APIs behave the same?
| Topic | tinypool 2.2.0 | piscina 5.3.2 |
|---|---|---|
| Worker entry | filename + default export | filename + default export |
| Run | pool.run(task) | pool.run(task) |
| Thread caps | minThreads / maxThreads | minThreads / maxThreads |
| Teardown | destroy() | destroy() |
| Result on my fixture | 4950 | 4950 |
Basic run/destroy parity held. piscina still owns the richer move / TransferList story I did not exercise. Monorepo task runners that compete with worker pools for "how do I parallelize work" sit next to Turbo vs Nx and Turbo vs Lage.
Which one should you pick?
| Situation | My pick |
|---|---|
| Vitest stack, want the thin pool | tinypool |
| Smallest node ESM pool bundle on this box | tinypool |
| Need TransferList / move helpers | piscina |
| Want the Node foundation worker-pool docs surface | piscina |
| Browser E2E, not worker pools | look at Playwright vs Cypress instead |
Bottom line: tinypool 2.2.0 was 5,385 B gzip versus 9,994 B for piscina 5.3.2, and tinypool's 2k-task medians were about 25–27 ms versus about 29–37 ms for piscina on this box. Who should not switch: codebases that already depend on piscina's move/TransferList paths, or teams standardized on piscina's option names in shared infra.
How this was made: I installed both packages on the ShopperCove box, measured esbuild node bundles, timed 2,000 worker tasks in two order-reversed runs, and checked result parity plus destroy. The JSON results sit next to the scripts. The write-up was drafted with AI help and checked against that output.
Sources
- https://github.com/tinylibs/tinypool
- https://github.com/piscinajs/piscina
- https://www.npmjs.com/package/tinypool
- https://www.npmjs.com/package/piscina
Related
- https://www.shoppercove.com/blog/bun-test-vs-vitest
- https://www.shoppercove.com/blog/jest-vs-vitest
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/tinyexec-vs-execa
- https://www.shoppercove.com/blog/turbo-vs-nx
- https://www.shoppercove.com/blog/turbo-vs-lage
- https://www.shoppercove.com/blog/c8-vs-nyc
- https://www.shoppercove.com/blog/playwright-vs-cypress
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~02:22 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). tinypool 2.2.0 vs piscina 5.3.2, esbuild 0.28.2 node ESM minify + gzip -9. Size: 17,087/5,385 B vs 35,571/9,994 B. Speed 2,000 tasks x 4 threads, 9-round median, order-reversed (ms): file1 tinypool 25.804/25.020 vs piscina 36.542/29.542; file2 26.996/25.425 vs 31.161/30.914. Result parity 4950. Disk ~50 KB vs ~425 KB. Not tested: TransferList/move, AbortSignal load, Windows, Deno/Bun. No affiliate.