ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 65

  1. Blog

confbox vs dotenv: 0.062 ms vs 0.026 ms on 50 Keys

Aditya Challa·5 October 2026·6 min read

Hands-on
On this page
  1. What I tested
  2. How fast is confbox vs dotenv?
  3. What does each one cost to install and bundle?
  4. Do they return the same shape?
  5. Which one should you pick?
  6. Sources
  7. Related

I parsed the same 50-key KEY=VALUE blob on this box: dotenv 18.0.5 took about 0.026 ms with the default parser (about 0.010 ms with fast: true), while confbox 0.3.1 parseINI took about 0.062 ms. confbox's tree-shaken INI entry gzipped to 1,537 B against dotenv's 4,938 B, and confbox parseTOML on a small typed config was about 0.0047 ms.

Short answer: keep dotenv when you want .env files injected into process.env. Reach for confbox when you load TOML, YAML, JSONC, JSON5 or INI as plain objects without touching the environment, especially if you only import the one format you need. 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 03:45 IST.
  • Versions: confbox 0.3.1, dotenv 18.0.5 (both npm latest that day), Node 20.19.2, esbuild 0.28.2 node ESM minify + gzip -9.
  • Inputs: a 50-key .env-style string (1,640 B) and a 500-key string (20,280 B); a small TOML/YAML/JSON5/JSONC/JSON config with nested tables; dotenv.config against a real fixture/.env file versus parseTOML on fixture/config.toml. Median of 9 rounds × 2,000 ops, two processes with the library order reversed. Scripts and JSON in /workspace/bench-confbox-dotenv/.
  • Behavior checks: quotes, empty values, equals inside values, unexpanded dollar HOST references, type differences (string vs number/bool), whether config() mutates process.env, and TOML round-trip.
  • Not tested: dotenv expand / variable interpolation packages, multiline values beyond escaped newlines, browser runtimes, Bun/Deno hosts, c12 as a full config loader on top of confbox, and adversarial multi-megabyte files.

How fast is confbox vs dotenv?

Job (median ms/op, avg of 2 order-reversed runs)dotenv 18.0.5confbox 0.3.1
50-key KEY=VALUE parse0.02620.0617 (parseINI)
50-key with fast: true0.0098—
500-key KEY=VALUE parse0.23770.6522 (parseINI)
500-key with fast: true0.1059—
Small TOML config—0.0047
Small YAML config—0.0554
Small JSON5 / JSONC / JSON—0.0247 / 0.0069 / 0.0014
dotenv.config file / parseTOML file0.10370.0093

On plain .env text, dotenv wins: about 2.4× faster than parseINI at 50 keys, and its fast scanner is another 2–3× on top. Once the config is structured TOML, confbox is in a different league (about 0.005 ms) and still faster than dotenv.config's file read+parse path here. If you already compared TOML parsers, confbox ships smol-toml under the hood — see smol-toml vs @iarna/toml. YAML cost lines up with the wider yaml vs js-yaml tradeoff.

What does each one cost to install and bundle?

Build (esbuild minify + gzip -9)MinifiedgzipInputs
dotenv (parse + config)11,431 B4,938 B2
confbox/ini only3,194 B1,537 B6
confbox/toml only13,409 B5,108 B5
confbox/yaml only57,939 B17,608 B5
confbox/json5 only29,438 B8,775 B6
confbox full export102,321 B31,519 B16

Fresh install: dotenv about 84 KB on disk (1 package), confbox about 232 KB (1 package, formats vendored into dist). Tree-shaking matters: import from confbox/ini and you beat dotenv on gzip; import the whole barrel and you do not. Lock the chosen entry in CI with size-limit vs bundlesize. Parsed objects often get merged with defaults next — that path is measured in defu vs lodash.merge.

Do they return the same shape?

Checkdotenv 18.0.5confbox 0.3.1
50 KEY=VALUE keys parsed54 (incl. quotes / empty)54 via parseINI
QUOTE=hello worldstring hello worldstring hello world
HAS_EQ=a=b=ca=b=ca=b=c
EXPAND references HOSTleft as literal dollar HOSTleft as literal (INI)
PORT=3000 / DEBUG=true typesalways stringsTOML: number / boolean
config() / parse side effectswrites process.envpure parse, no env writes
Formats in one package.env onlyINI, TOML, YAML, JSON, JSON5, JSONC

dotenv is an env injector that also exposes parse(). confbox is a format toolbox: same INI keys as dotenv on my fixture, but TOML/YAML give real types and nested tables. For loose JSON-ish strings that are not .env files, destr vs superjson is the closer sibling. Path joins around config files are covered in pathe vs node:path.

Which one should you pick?

SituationMy pick
Twelve-factor .env into process.envdotenv
Hot parse of large .env textdotenv with fast: true
App config as TOML or YAML with typesconfbox (toml or yaml entry)
Smallest bundle for KEY=VALUE onlyconfbox/ini
Need every format in one dependencyconfbox (import only what you use)
Full layered config loader (rc files, overrides)c12 on top of confbox, not dotenv alone

Bottom line: on this box dotenv 18.0.5 parsed 50 .env keys in about 0.026 ms (0.010 ms fast) versus confbox parseINI at about 0.062 ms, while confbox/ini was the smaller gzip (1.5 KB vs 4.9 KB) and confbox TOML handled typed config in about 0.005 ms without touching process.env. Who should not switch off dotenv: services that rely on config() mutating the environment early in boot. Who should not force .env for everything: tools that already speak TOML/YAML and want typed nested config.

How this was made: I installed both packages on the ShopperCove box, timed parse paths over 2,000 ops × 9 rounds in two order-reversed processes, bundled dotenv and each confbox entry with esbuild, and checked quoting, types, env mutation and TOML round-trips. 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/confbox
  • https://github.com/motdotla/dotenv
  • https://www.npmjs.com/package/confbox
  • https://www.npmjs.com/package/dotenv
  • https://toml.io/
  • https://esbuild.github.io/

Related

  • https://www.shoppercove.com/blog/smol-toml-vs-iarna-toml
  • https://www.shoppercove.com/blog/yaml-vs-js-yaml
  • https://www.shoppercove.com/blog/destr-vs-superjson
  • https://www.shoppercove.com/blog/defu-vs-lodash-merge
  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/pathe-vs-node-path
  • https://www.shoppercove.com/blog/ohash-vs-object-hash
  • https://www.shoppercove.com/blog/knip-vs-depcheck
confboxdotenvparsingperformancebundle sizetomlyamljson

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~03:45 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). confbox 0.3.1 vs dotenv 18.0.5; esbuild 0.28.2. 50-key .env-style 1,640 B and 500-key 20,280 B; small TOML/YAML/JSON5/JSONC/JSON configs; median of 9 rounds × 2,000 ops, order reversed (ms): dotenv.parse 0.0262/0.0262, fast 0.0085/0.0111, 500-key 0.2444/0.2310 vs parseINI 0.0666/0.0568 and 0.6620/0.6423; parseTOML 0.0048/0.0047; YAML 0.0548/0.0559. dotenv.config file 0.1037 vs parseTOML file 0.0093. Bundle gzip dotenv 4,938 B; confbox/ini 1,537; toml 5,108; yaml 17,608; json5 8,775; full 31,519. Install ~84 KB vs ~232 KB. Behavior: same 54 INI keys; types always string in dotenv, real number/bool in TOML; config() writes process.env, confbox does not; dollar HOST left literal in both. Not tested: dotenv-expand, c12, browsers, Bun/Deno, huge adversarial files. No affiliate.

Notes when a lab post goes up

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

Related links

  • Plate 35

    destr vs superjson: 665 B vs 4.1 KB Gzip

    5 Oct 2026

  • 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

On this page

  1. What I tested
  2. How fast is confbox vs dotenv?
  3. What does each one cost to install and bundle?
  4. Do they return the same shape?
  5. Which one should you pick?
  6. Sources
  7. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove