Plate 35
cookie-es vs cookie: 2.3 KB vs 1.4 KB Gzip
Aditya Challa5 min read
I bundled the two Cookie-header helpers on this box: cookie-es 3.1.1 came out at 2,295 bytes gzip for the full export set, while jshttp cookie 2.0.1 came out at 1,446 bytes. Cookie-header parse matched on my fixtures. Set-Cookie parse favored cookie (~1.2 µs vs ~2.0 µs per three-header pass).
Short answer: pick cookie when you want the smaller modern API (object stringify + Set-Cookie helpers). Keep cookie-es when you still call serialize(name, value, options) the Express way, or when you need splitSetCookieString. 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:55 IST.
- Versions: cookie-es 3.1.1, cookie 2.0.1, Node 22.20.0, esbuild 0.28.2 minify + gzip -9 (browser and node platforms matched).
- Inputs: five Cookie header strings (short, eight pairs, 64-char token, empty value, percent-encoded JSON); three Set-Cookie strings. Speed: 200,000 outer iters, median of 9 rounds, two order-reversed runs. Scripts in /workspace/bench-cookie-es-cookie/.
- Findings: full gzip 2,295 B vs 1,446 B; parse-only 512 B vs 420 B. parseCookie on five headers ~1.65 / 1.60 µs (cookie-es) vs ~1.67 / 1.62 µs (cookie). parseSetCookie on three headers ~2.04 / 1.98 µs vs ~1.20 / 1.17 µs.
- One surprise: cookie 2.x dropped the classic serialize(name, value) signature. stringifyCookie takes a Cookies object. Passing a string name iterates characters and emits 0=s; 1=e; … — easy footgun if you migrate from cookie 0.x/1.x or from cookie-es.serialize.
- Not tested: browsers, signed cookies, tough-cookie jar behavior, or http2 trailer edge cases.
How much smaller is cookie?
| Build (esbuild minify, gzip -9) | Minified | gzip |
|---|---|---|
| cookie-es full exports | 6,044 B | 2,295 B |
| cookie full exports | 3,663 B | 1,446 B |
| cookie-es parseCookie only | 901 B | 512 B |
| cookie parseCookie only | 753 B | 420 B |
cookie wins size on both the full API and the parse-only cut. Track the delta the same way as size-limit vs bundlesize. Other unjs vs stdlib swaps in this series include pathe vs node:path and klona vs structuredClone.
Do parse results match?
| Check | cookie-es 3.1.1 | cookie 2.0.1 |
|---|---|---|
| parseCookie on mixed header | same object keys/values | same |
| parseSetCookie Max-Age / SameSite | same fields | same |
| stringify multi Cookie object | session=abc; theme=dark | session=abc; theme=dark |
| serialize(name, value, opts) | yes (classic) | no — use stringifySetCookie |
| splitSetCookieString | yes | no |
Header parse matched byte-for-byte on my fixture (including a percent-decoded space). The API shape is the real decision. cookie-es keeps Express-era serialize; cookie 2.x wants objects. If your stack already leans unjs for HTTP clients, compare ky vs axios. Request mocking sits next door in msw vs nock.
Is Set-Cookie parse speed a reason to switch?
| Cost (200k outer iters, median of 9, 2 runs) | cookie-es | cookie |
|---|---|---|
| parseCookie (5 headers), µs / outer | 1.65 / 1.60 | 1.67 / 1.62 |
| parseSetCookie (3 headers), µs / outer | 2.04 / 1.98 | 1.20 / 1.17 |
| serialize name/value or stringify one key, ns | ~241 / 220 (serialize) | ~93 / 101 (stringify obj) |
Cookie-header parse is a wash. Set-Cookie parse and simple stringify favored cookie on this box. For edge middleware that only reads Cookie headers, size and API matter more than the nanoseconds. Schema validation at the boundary is a different tool; see zod vs valibot and ajv vs zod.
Which one should you pick?
| Situation | My pick |
|---|---|
| New code, want smaller bundle | cookie 2.x |
| Need stringifySetCookie / parseSetCookie only | cookie 2.x |
| Existing serialize(name, value, options) call sites | cookie-es |
| Need splitSetCookieString for combined Set-Cookie | cookie-es |
| Migrating from cookie 1.x serialize without rewriting | cookie-es first, or rewrite to objects |
Bottom line: cookie 2.0.1 was 1,446 B gzip versus 2,295 B for cookie-es 3.1.1, with matching Cookie-header parse and faster Set-Cookie parse on this box. Who should not switch yet: codebases with hundreds of serialize(name, value) call sites and no time to move to object stringify. Config and merge helpers nearby include defu vs lodash.merge.
How this was made: I installed both packages on the ShopperCove box, measured esbuild bundles, timed parse/serialize/Set-Cookie loops in two order-reversed runs, and compared parse outputs on shared fixtures. 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/unjs/cookie-es
- https://github.com/jshttp/cookie
- https://www.npmjs.com/package/cookie-es
- https://www.npmjs.com/package/cookie
Related
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/pathe-vs-node-path
- https://www.shoppercove.com/blog/klona-vs-structuredclone
- https://www.shoppercove.com/blog/ky-vs-axios
- https://www.shoppercove.com/blog/msw-vs-nock
- https://www.shoppercove.com/blog/zod-vs-valibot
- https://www.shoppercove.com/blog/ajv-vs-zod
- https://www.shoppercove.com/blog/defu-vs-lodash-merge
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~01:55 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). cookie-es 3.1.1 vs cookie 2.0.1, esbuild 0.28.2 minify + gzip -9. Size: cookie-es full 6,044/2,295 B vs cookie 3,663/1,446 B; parse-only 901/512 vs 753/420. Speed (200,000 outer iters, 9-round median, order-reversed): parseCookie 5-header pass ces 1,649.7 / 1,604.6 ns vs cookie 1,673.5 / 1,624.8 ns; parseSetCookie 3-header ces 2,037.9 / 1,983.2 vs cookie 1,196.5 / 1,174.0; ces serialize name/value 241.1 / 220.0 ns vs cookie stringify one-key 92.9 / 100.5 ns. Behavior: parseCookie values matched; cookie 2.x stringifyCookie is object-only; cookie-es retains serialize(name,value,opts) and splitSetCookieString. Not tested: browsers, signed cookies, tough-cookie jars, HTTP/2 trailers. No affiliate.