Plate 64
Ky vs Axios: 9.8 KB vs 19.6 KB Gzip
Aditya Challa4 min read
I bundled the browser HTTP clients on this box: ky 2.1.0 came in at 9,777 B gzip against axios 1.20.0 at 19,559 B. On a localhost JSON GET loop, ky sat at about 365 us per request and axios at about 269 us.
Short answer: pick ky when you want a Fetch-based client at about half the gzip weight. Pick axios when you need broad adapters, upload progress, or the older XHR path. 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 01:01–01:02 IST.
- Versions: ky 2.1.0, axios 1.20.0, Node 22.20.0 (built-in fetch), esbuild 0.28.2 minify + gzip -9.
- Fixture: /workspace/bench-ky-axios/. Browser size: ky.get(url).json() vs axios.get(url).then(r => r.data). Also ky.create() and axios.create(). Speed: local http.Server returning a 32-byte JSON body; 500 sequential GETs × 9 rounds (median) after warm.
- Findings: gzip 9,777 B vs 19,559 B for the simple get helpers; create wrappers 9,817 B vs 19,598 B. Median loop 182.714 ms vs 134.455 ms for 500 requests (about 365 vs 269 us/req; 2,737 vs 3,719 req/s). Disk trees about 720 KB vs 2.2 MB.
- One surprise: axios was faster on this sequential localhost JSON path even while shipping about 2× the gzip. The size win for ky is clear; the raw Node loop is not.
- Not tested: browser XHR path, upload progress, interceptors under load, retries/timeouts at scale, React Query / SWR wrappers, HTTPS, HTTP/2, or FormData multipart.
How wide was the size gap?
| Browser build (esbuild minify) | Minified | gzip -9 |
|---|---|---|
| ky.get().json() | 28,589 B | 9,777 B |
| axios.get().then | 51,098 B | 19,559 B |
| ky.create() | 28,682 B | 9,817 B |
| axios.create() | 51,187 B | 19,598 B |
ky was about 2.0× smaller gzip on both the one-shot and create entries. Track shipped weight with size-limit vs bundlesize. Mock the same clients in tests with msw vs nock.
How fast were the localhost GETs?
| Path (500 sequential JSON GETs, median of 9) | ky | axios |
|---|---|---|
| Local http.Server, 32-byte body | 182.714 ms (365 us/req) | 134.455 ms (269 us/req) |
On this box axios completed the sequential loop about 1.36× faster. That does not erase a ~10 KB gzip gap on the browser build. Request harness notes sit next to my Jest vs Vitest write-up when I pull these clients into a test runner.
Which one should you pick?
| Situation | My pick |
|---|---|
| Browser app on Fetch, watch the gzip budget | ky |
| Need axios interceptors / upload progress / older Node | axios |
| New greenfield Fetch-first client | ky |
| Migrating a large axios codebase | stay on axios unless size is the blocker |
| Bundle budget under about 12 KB gzip for HTTP | ky |
Bottom line: ky 2.1.0 shipped 9.8 KB gzip against axios 1.20.0 at 19.6 KB, while axios won the sequential localhost JSON loop (269 vs 365 us/req). Who should not switch: teams already deep in axios adapters and interceptors — rewrite cost beats a 10 KB gzip win if size is not the constraint. Validate payloads with Zod vs Valibot. Unused-export cleanup: knip vs depcheck.
How this was made: I installed ky and axios on the ShopperCove box, measured esbuild minify+gzip browser sizes, timed sequential localhost JSON GETs, and recorded the JSON. The write-up was drafted with AI help and checked against that output.
Sources
- https://github.com/sindresorhus/ky
- https://www.npmjs.com/package/ky
- https://github.com/axios/axios
- https://www.npmjs.com/package/axios
Related
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/msw-vs-nock
- https://www.shoppercove.com/blog/jest-vs-vitest
- https://www.shoppercove.com/blog/knip-vs-depcheck
- https://www.shoppercove.com/blog/zod-vs-valibot
- https://www.shoppercove.com/blog/ajv-vs-zod
- https://www.shoppercove.com/blog/biome-vs-eslint-prettier
- https://www.shoppercove.com/blog/oxlint-vs-eslint
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~01:01-01:02 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0 with fetch). ky 2.1.0 vs axios 1.20.0, esbuild 0.28.2. Fixture /workspace/bench-ky-axios/: browser entries ky.get().json vs axios.get().then; create with prefix/baseURL. Speed: local http.Server 32-byte JSON, 500 sequential GETs x 9 rounds (median) after warm. Medians: gzip 9,777 vs 19,559 B; create 9,817 vs 19,598 B; loop 182.714 vs 134.455 ms (365 vs 269 us/req). Disk ~720 KB vs ~2.2 MB. Raw: res-bundle.json, res-speed.json. Not tested: XHR, upload progress, interceptors under load, retries at scale, React Query/SWR, HTTPS/HTTP2, multipart. No affiliate.
Related links
Plate 17
Immer vs Mutative: 86 us vs 3 us per Update
5 Oct 2026
Plate 48
Zod vs Valibot: 1.14M vs 0.97M Parses
zod 4.6.5 vs valibot 1.5.0 on one nested user schema (uuid/email/age/tags/profile/enum). Warm medians after 2k warmup + 9×50k: zod.parse 1,144,494 ops/s vs valibot.parse 968,187 (~1.18×). safeParse fail: valibot 697,760 vs zod 415,523 (~1.7×). esbuild minify+gzip9: 452,999/92,636 B vs 85,126/15,422 B. Package trees ~6.1 MB vs ~1.9 MB. Fixture /workspace/bench-zod-valibot/.
5 Oct 2026
Plate 26
Picocolors vs Chalk: 1.0 KB vs 3.4 KB Gzip
5 Oct 2026