deep-dives·2026-06-23·3 min read

Performance and Bundle Size

CtroEnv's zero-dependency core is 6.5 KB gzipped — here's how it stays lean.

Ctrotech·
guideperformance
Featured image for Performance and Bundle Size
RSS Feed

Performance and Bundle Size

CtroEnv's core package has zero runtime dependencies and ships at 6.5 KB gzipped. Here's how it stays lean and what that means for your app.

Size Breakdown

PackageGzippedDependencies
@ctroenv/core6.5 KBZero
@ctroenv/cli~50 KBCLI tools only
@ctroenv/node~3 KBZero (uses Node built-ins)
@ctroenv/vite~2 KBZero
@ctroenv/nextjs~2 KBnext (peer)
@ctroenv/shared~1 KBZero

Compare with alternatives that bundle zod (~50 KB):

LibraryCore sizeDependencies
CtroEnv6.5 KBnone
envalid9 KBnone
t3-env~55 KBzod (~50 KB)
zod~50 KBnone

How Zero Dependencies Stays Fast

The core package implements everything from scratch:

  • Parsing — Each validator has a hand-written parse function. No generic schema parser.
  • Validation — Refinements wrap the base parse function. Single-pass execution.
  • Type inference — Pure TypeScript types erased at compile time. Zero runtime cost.
  • Proxy masking — The Proxy is created once during defineEnv() and has O(1) property access.

Validation Overhead

Validation runs once during defineEnv(). After that, env property access is a direct Proxy trap:

const env = defineEnv(schema)  // validation runs here
env.PORT                        // O(1) — no re-validation
env.DATABASE_URL                // O(1)

This means validation cost is paid exactly once per process lifetime, no matter how many times you access env vars.

Tree Shaking

CtroEnv is fully tree-shakeable. Import only what you use:

// Only string() and number() are bundled
import { defineEnv, string, number } from "@ctroenv/core"

// pick(), boolean(), ip(), semver(), uuid(), guid() are excluded

All packages have "sideEffects": false in their package.json.

Build Size Impact

In a typical Next.js app:

Total bundle size (client):
  CtroEnv: 0 KB (server-only)
  t3-env + zod: ~55 KB

Total bundle size (server):
  CtroEnv: 6.5 KB
  t3-env + zod: ~55 KB

CtroEnv is server-only in Next.js (client vars are prefixed with NEXT_PUBLIC_). The zero-dependency core means no zod payload on the server either.

Benchmark

Validation of a 10-variable schema:

OperationTime
Define schema< 0.1 ms
defineEnv() with all vars valid~0.3 ms
defineEnv() with errors~0.4 ms
Property access (after validation)< 0.01 ms

Measured with Vitest bench on Node 22. Your mileage depends on schema complexity and string parsing overhead.

When Bundle Size Matters

  • Serverless functions — Cold starts are faster with fewer bytes to load
  • Edge runtimes — Cloudflare Workers, Deno Deploy, and Vercel Edge have strict size limits
  • CLI tools — Faster installs, smaller node_modules
  • CI pipelines — Less network overhead in container builds
More deep-dives posts
Previous postUsing CtroEnv in Deno and BunNext postUsing CtroEnv on Cloudflare Workers

On this page

Size BreakdownHow Zero Dependencies Stays FastValidation OverheadTree ShakingBuild Size ImpactBenchmarkWhen Bundle Size Matters