ADR-0005 Input validation
Company standard validation library — Zod, at every system boundary.
- Decision
- ZodBuild the app
- Status
- Accepted
- Date
- Scope
- Company-wide default for all new apps
Connections
Context
Section titled “Context”Every app validates data at its boundaries: API request payloads (server routes, ADR-0036), form submissions, environment variables at boot, URL params, and third-party webhook payloads. TypeScript types are erased at runtime — without runtime validation, any from the network flows straight into business logic.
Requirements:
- Runtime validation with static type inference — one schema produces both the validator and the TS type
- Works in our API routes — plain
safeParsein server-route handlers - Integrates with TanStack Form/Router on the client — via Standard Schema, the shared spec all major validation libs now implement
- One library everywhere — server and client share schemas; no duplicated validation logic
Options considered
Section titled “Options considered”1. Zod
Section titled “1. Zod”The incumbent. Schema-first, excellent type inference, enormous ecosystem. v4 shipped a rewritten core with major performance gains and first-party Standard Schema support.
Pros
- Largest ecosystem and mindshare — every tool has a Zod adapter first
- First-party Hono integration:
@hono/zod-validator - Standard Schema compliant → plugs into TanStack Form/Router directly
- Single source of truth: schema → inferred TS type → Hono validator → form validator
@hono/zod-openapiturns schemas into OpenAPI specs- Zod 4 core rewrite closes the historical performance gap
Cons
- Largest client-side bundle of the candidates (mitigated by v4 tree-shaking)
- API surface is broad; team should stick to a common subset
2. Valibot
Section titled “2. Valibot”Modular, tree-shakeable alternative with near-identical API.
Pros
- Smallest bundles; modular imports
- Standard Schema compliant
Cons
- Smaller ecosystem; adapters exist but land later than Zod’s
- Less Stack Overflow coverage, fewer hiring-pool developers know it
3. ArkType
Section titled “3. ArkType”Type-syntax-as-validation, extremely fast.
Pros
- Fastest validation of the three
- Elegant: validators written in TypeScript’s own type syntax
Cons
- Youngest; steepest learning curve (a new DSL, however familiar it looks)
- Smallest ecosystem and community
4. Yup / TypeBox / io-ts
Section titled “4. Yup / TypeBox / io-ts”Yup is dated and weaker on inference; TypeBox is JSON-Schema-centric (great for OpenAPI, clunkier DX); io-ts is FP-heavy. All viable, none a better default.
Decision
Section titled “Decision”Zod is the company-standard validation library, used at every system boundary:
- API routes —
safeParsethroughreadJsonandreadQueryin the server-route handlers (ADR-0036). (Amended 2026-11-13: this ADR first named@hono/zod-validator; ADR-0036 replaced Hono with Start’s server routes.) - Server functions — the schema passed to
.validator(); they are endpoints anyone can call, not just our UI - Env vars — parsed once at boot; the app crashes fast on misconfiguration
- Forms — shared schemas feed TanStack Form through Standard Schema
- Webhooks / external payloads — validated at ingress, never trusted
The deciding factors: the largest ecosystem, first-party adapters for everything in our stack (TanStack, and Hono where a product adopts it), Standard Schema compliance keeping us portable, and one-schema-one-type as the single source of truth. We accept the bundle-size cost, mitigated by Zod 4 tree-shaking and by sharing schemas instead of duplicating them.
Consequences
Section titled “Consequences”Easier:
- API payloads, env config, and forms all speak one schema language — less context-switching
- Schemas are shared between client and server; drift between client-side and server-side validation becomes impossible
- OpenAPI generation, for a product that publishes an API (ADR-0036), comes nearly free from the same schemas
- Boot-time env validation catches ops misconfiguration before the first request
Harder:
- Client bundles carry a validation lib — acceptable, but schemas should be shared and tree-shaken, not pasted per-form
- Discipline required to validate at boundaries only — not re-validating already-trusted internal data
Given up: Valibot’s smaller bundles and ArkType’s raw speed. Accepted — ecosystem gravity and integration coverage outweigh both at our scale.

