Performance and Bundle Size
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
| Package | Gzipped | Dependencies |
|---|---|---|
@ctroenv/core | 6.5 KB | Zero |
@ctroenv/cli | ~50 KB | CLI tools only |
@ctroenv/node | ~3 KB | Zero (uses Node built-ins) |
@ctroenv/vite | ~2 KB | Zero |
@ctroenv/nextjs | ~2 KB | next (peer) |
@ctroenv/shared | ~1 KB | Zero |
Compare with alternatives that bundle zod (~50 KB):
| Library | Core size | Dependencies |
|---|---|---|
| CtroEnv | 6.5 KB | none |
| envalid | 9 KB | none |
| t3-env | ~55 KB | zod (~50 KB) |
| zod | ~50 KB | none |
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:
| Operation | Time |
|---|---|
| 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