ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 35

  1. Blog

destr vs superjson: 665 B vs 4.1 KB Gzip

Aditya Challa·5 October 2026·5 min read

Hands-on
On this page
  1. What I tested
  2. How much smaller is destr?
  3. Do the behaviors match?
  4. Is plain-parse speed a reason to skip destr?
  5. Which one should you pick?
  6. Sources
  7. Related

I bundled JSON helpers on this box: destr 2.0.5 came out at 665 bytes gzip, while superjson 2.2.6 came out at 4,100 bytes. On plain objects, JSON.parse was fastest (~0.44 µs); destr sat near ~0.58 µs. Only superjson round-tripped Date, Set, undefined, and NaN.

Short answer: pick destr when you want a safer drop-in for JSON.parse on possibly-not-JSON strings. Pick superjson when the wire format must revive rich types. Do not treat them as the same tool. 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:20 IST.
  • Versions: destr 2.0.5, superjson 2.2.6, Node 22.20.0 JSON, esbuild 0.28.2 browser ESM minify + gzip -9.
  • Inputs: a plain five-field JSON string for parse; a rich object with Date, undefined, NaN, and Set([1]) for SuperJSON stringify/parse. Speed: 100,000 calls, median of 9 rounds, two order-reversed runs. Scripts in /workspace/bench-destr-superjson/.
  • Findings: destr 1,305 / 665 B; superjson 11,447 / 4,100 B; JSON re-export 69 / 70 B. Plain parse ~590 / 564 ns (destr), ~589 / 585 (safeDestr), ~441 / 444 (JSON.parse). SuperJSON rich parse ~2,967 / 2,999 ns; rich stringify ~6,787 / 6,765 ns.
  • One surprise: SuperJSON.parse on a plain {"a":1} string returned undefined. It expects its own {json, meta} envelope from SuperJSON.stringify. destr("0123") returned the string "0123" while JSON.parse threw.
  • Not tested: custom SuperJSON class registries, streaming parsers, MessagePack alternatives, or browser DevTools size after tree-shaking beyond this esbuild cut.

How much smaller is destr?

Build (esbuild minify, gzip -9)Minifiedgzip
destr + safeDestr1,305 B665 B
superjson (parse/stringify/serialize exports)11,447 B4,100 B
JSON.parse / JSON.stringify re-export69 B70 B

destr is the small safe-parse helper. superjson is a typed transport layer. Native JSON stays free. Measure the delta like size-limit vs bundlesize. Other parse/format swaps in this series: smol-toml vs @iarna/toml and yaml vs js-yaml.

Do the behaviors match?

Checkdestr 2.0.5superjson 2.2.6JSON
plain {"a":1,"b":"hi"}{a:1,b:"hi"}parse → undefined (needs envelope){a:1,b:"hi"}
string "0123""0123" (no throw)n/athrows
string "undefined"undefinedn/athrows
Date / Set / undefined / NaN round-tripno (plain JSON loses them)yes via metaDate→ISO string; Set→{}; undefined dropped; NaN→null
safeDestr('{bad')throws SyntaxErrorn/athrows

destr is tolerant of values that look like JSON but are not. superjson is strict about its envelope and richer about types. Schema validation after parse is a separate layer; see zod vs valibot and ajv vs zod.

Is plain-parse speed a reason to skip destr?

Cost (100k calls, median of 9, 2 runs, ns/op)Run 1Run 2
destr(plain)590.2563.5
safeDestr(plain)589.4585.1
JSON.parse(plain)440.9444.2
SuperJSON.parse(rich envelope)2,966.62,998.8
SuperJSON.stringify(rich)6,787.16,765.4

On known-good JSON, JSON.parse won. destr paid a small tax for the safe path. SuperJSON's cost is in a different job: carrying types across the wire. Deep clone and hash helpers nearby: klona vs structuredClone and ohash vs object-hash. HTTP body clients: ky vs axios.

Which one should you pick?

SituationMy pick
Parsing env vars / loosely typed strings that might not be JSONdestr or safeDestr
Known-good JSON from your own APIJSON.parse
Need Date, Map, Set, undefined, NaN across RPCsuperjson
Bundle budget under 1 KB for parse helperdestr
Prefer zero deps and you control both endsJSON + explicit ISO fields

Bottom line: destr 2.0.5 was 665 B gzip versus 4,100 B for superjson 2.2.6. Plain parse favored JSON.parse; only superjson kept rich types. Who should not add superjson: services that already send ISO strings and do not need Set/Map revival. Cookie and merge helpers next door: cookie-es vs cookie and defu vs lodash.merge.

How this was made: I installed both packages on the ShopperCove box, measured esbuild bundles, timed plain and rich parse/stringify loops in two order-reversed runs, and compared behavior 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/destr
  • https://github.com/ravionhq/superjson
  • https://www.npmjs.com/package/destr
  • https://www.npmjs.com/package/superjson

Related

  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/smol-toml-vs-iarna-toml
  • https://www.shoppercove.com/blog/yaml-vs-js-yaml
  • https://www.shoppercove.com/blog/zod-vs-valibot
  • https://www.shoppercove.com/blog/ajv-vs-zod
  • https://www.shoppercove.com/blog/klona-vs-structuredclone
  • https://www.shoppercove.com/blog/ohash-vs-object-hash
  • https://www.shoppercove.com/blog/ky-vs-axios
destrsuperjsonjsonserializationbundle sizeperformanceparsingjavascript

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~02:20 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). destr 2.0.5 vs superjson 2.2.6, esbuild 0.28.2 minify + gzip -9. Size: destr 1,305/665 B vs superjson 11,447/4,100 B vs JSON re-export 69/70 B. Speed (100,000 calls, 9-round median, order-reversed, ns/op): destr plain 590.2 / 563.5; safeDestr 589.4 / 585.1; JSON.parse 440.9 / 444.2; SuperJSON rich parse 2,966.6 / 2,998.8; rich stringify 6,787.1 / 6,765.4. Behavior: SuperJSON.parse on plain JSON → undefined; destr tolerates "0123"; rich Date/Set/undefined/NaN only via SuperJSON. Not tested: custom class registries, streaming parsers, MessagePack. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 38

    smol-toml vs @iarna/toml: 3x Faster on Deno Cargo

    5 Oct 2026

  • Plate 18

    yaml vs js-yaml: 11x Faster Parse vs Kept Comments

    5 Oct 2026

  • Plate 33

    ufo vs URL: 2.4 KB vs 0.5 KB Gzip

    5 Oct 2026

On this page

  1. What I tested
  2. How much smaller is destr?
  3. Do the behaviors match?
  4. Is plain-parse speed a reason to skip destr?
  5. Which one should you pick?
  6. Sources
  7. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove