AJV vs Zod vs Valibot: Schema Validation 2026
AJV vs Zod vs Valibot: Schema Validation 2026
TL;DR
AJV, Zod, and Valibot are not interchangeable — they target different problems. AJV is the JSON Schema standard implementation: 85M+ weekly downloads, 14M ops/sec, and the right tool for server-side validation where performance is critical. Zod is the TypeScript developer's choice: type inference that eliminates duplicate schema/type definitions, with a best-in-class DX. Valibot is the bundle-size winner: modular tree-shaking gets validation down to under 1KB for simple forms, ideal for client-side code. If you're starting a new Node.js API in 2026, Zod or Valibot. If you're validating JSON payloads at scale (OpenAPI, config files, streaming data), AJV.
Key Takeaways
- AJV is 7× faster than Zod — 14M ops/sec vs 2M ops/sec on simple object validation benchmarks
- Valibot bundles at 1.37KB vs Zod's 17.7KB — 90% smaller for a simple login form validator
- AJV uses JSON Schema (IETF standard) — schemas are language-portable, work across Python, Go, Java
- Zod infers TypeScript types automatically — write your schema once, get runtime validation + compile-time types
- Valibot v1 matches Zod v4 on runtime speed — the bundle size advantage is Valibot's main differentiator
- AJV dominates npm downloads (85M/week) because it powers linting tools, bundlers, and OpenAPI validators — not just app code
The Problem These Libraries Actually Solve
Before comparing, it's worth being precise about what each library is designed for — they have meaningful differences in philosophy.
AJV (Another JSON Schema Validator) implements the JSON Schema specification — an IETF standard used across dozens of programming languages. When you write a JSON Schema, it can be validated in Python, Go, Java, or JavaScript using native implementations. AJV is the JavaScript implementation, and it's used everywhere: eslint, webpack, ajv-formats, OpenAPI validators, IDE language servers. Most of AJV's 85M weekly downloads aren't from developers writing ajv.validate() directly — they're transitive dependencies of tools you already use.
Zod is a TypeScript-first schema builder that gives you both runtime validation and compile-time type inference from a single definition. It's purpose-built for TypeScript codebases:
import { z } from "zod";
const UserSchema = z.object({
name: z.string(),
age: z.number().positive(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>; // Free TypeScript type
The key insight: with Zod, you never write a separate TypeScript interface to match your validator. The schema is the type.
Valibot takes Zod's TypeScript-first approach but optimizes aggressively for bundle size through a modular, function-based API:
import { object, string, number, email, pipe, minValue } from "valibot";
const UserSchema = object({
name: string(),
age: pipe(number(), minValue(0)),
email: pipe(string(), email()),
});
Because Valibot's functions are individually importable, bundlers tree-shake everything you don't use. For a simple login form (email + password), the entire validator might be 600 bytes after tree-shaking.
Performance Benchmarks
Simple Object Validation (ops/sec)
| Library | ops/sec | Relative speed |
|---|---|---|
| AJV (JIT compiled) | 14,032,040 | 7× faster than Zod |
| Valibot v1 | 4,164,354 | 2× faster than Zod |
| TypeBox + AJV | 12,000,000+ | ~6× faster than Zod |
| Zod v4 | 1,985,027 | baseline |
| Zod v3 | ~1,000,000 | 0.5× Zod v4 |
AJV's speed advantage comes from JIT compilation — it analyzes your schema structure once and generates an optimized validation function. For a schema that never changes (which describes most production schemas), AJV pre-compiles the validator and subsequent calls are close to raw JavaScript performance.
Startup / Initialization Cost
AJV's JIT compilation isn't free at startup:
| Library | Import + schema compile time |
|---|---|
| Valibot | ~0.04ms |
| Zod | ~0.1ms |
| AJV (first validate) | ~4ms |
For serverless functions or edge runtime environments, AJV's 4ms schema compilation hit on cold start matters. For long-running Node.js servers, it's a one-time cost amortized across millions of requests.
Practical rule: AJV wins for high-volume server validation where you compile schemas once. Valibot/Zod win for short-lived environments or client-side code.
Bundle Size: The Client-Side Decision
For browser bundles, the difference is substantial:
| Library | Bundle size (simple login form) | Notes |
|---|---|---|
| Valibot v1 | 1.37 KB | Per-function imports, aggressive tree-shaking |
| Zod v4 (Mini) | 6.88 KB | New tree-shakable variant in v4 |
| Zod v4 (full) | 17.7 KB | Full import |
| AJV | 30+ KB | Not designed for browser bundles |
Valibot was built from the ground up for tree-shaking. When you import only object, string, and email from Valibot, that's literally all you ship. Zod v4 introduced "Zod Mini" — a tree-shakable variant that brings it to 6.88KB, narrowing the gap significantly.
For a Next.js app doing client-side form validation, the difference between Valibot's 1.37KB and Zod v4 full's 17.7KB can meaningfully affect Core Web Vitals on slow connections.
TypeScript Integration
Zod: Type Inference as the Core Feature
Zod's killer feature is bidirectional type inference:
// Define once
const ApiResponseSchema = z.object({
users: z.array(z.object({
id: z.string().uuid(),
role: z.enum(["admin", "user", "guest"]),
createdAt: z.string().datetime(),
})),
total: z.number(),
});
// Types derived automatically — no duplication
type ApiResponse = z.infer<typeof ApiResponseSchema>;
// { users: { id: string; role: "admin" | "user" | "guest"; createdAt: string }[]; total: number }
You can also use z.input<typeof Schema> for pre-transform input types and z.output<typeof Schema> for post-transform output types — essential for handling date string → Date object conversions.
Valibot: Same Inference, Smaller Bundle
Valibot v1 offers near-identical TypeScript inference to Zod:
import { object, string, number, pipe, email, minValue, InferOutput } from "valibot";
const UserSchema = object({ name: string(), age: pipe(number(), minValue(0)), email: pipe(string(), email()) });
type User = InferOutput<typeof UserSchema>;
The API is slightly more verbose — validators like email() and minValue() are applied with pipe() rather than chaining — but the TypeScript behavior is equivalent.
AJV: External Type Definitions Required
AJV uses JSON Schema, which predates TypeScript. By default, AJV validates and returns true/false with no TypeScript type narrowing:
import Ajv from "ajv";
const ajv = new Ajv();
const schema = {
type: "object",
properties: { name: { type: "string" }, age: { type: "number" } },
required: ["name", "age"],
};
const validate = ajv.compile(schema);
if (validate(data)) {
// data is still `any` here — no TypeScript inference
}
To get TypeScript types from AJV schemas, you need either:
ajv-ts— wraps AJV schemas with TypeScript genericsTypeBox— a TypeScript-first JSON Schema builder that integrates with AJV at full speed (12M+ ops/sec)- Manual interface definitions that mirror your schema (the old-school approach)
For TypeScript projects, TypeBox + AJV is the best of both worlds: TypeScript-safe schema definitions with AJV's raw validation speed.
When to Choose Each
Use AJV when:
- You need maximum throughput — validating thousands of records per second in a Node.js API
- You work with JSON Schema — OpenAPI spec validation, config file validation, schema registries
- Cross-language portability matters — your schemas need to work in Python, Go, or other services
- You're building tools — linters, bundlers, IDEs, and schema registries speak JSON Schema
- High-volume server-side validation — message queue processing, ETL pipelines, webhook handlers
// AJV + TypeBox: performance + TypeScript types
import { Type, TSchema } from "@sinclair/typebox";
import Ajv from "ajv";
const UserSchema = Type.Object({
name: Type.String(),
age: Type.Number({ minimum: 0 }),
});
const validate = new Ajv().compile(UserSchema);
// Full TypeScript type inference + AJV speed
Use Zod when:
- You're building TypeScript-first APIs — the type inference is the primary value
- Developer experience matters — Zod's error messages, transforms, and chaining API are excellent
- Server-side Next.js, tRPC, or Hono — ecosystem integration (tRPC uses Zod natively)
- Form validation with React Hook Form —
@hookform/resolvers/zodis the standard - Complex transformations —
.transform(),.preprocess(), coercion
Use Valibot when:
- Client-side form validation — bundle size is a real constraint
- Edge runtime — Cloudflare Workers, Vercel Edge, Deno — where startup time matters
- Framework-agnostic validation libraries — Valibot's modular API works anywhere
- You like Zod's ergonomics but need smaller bundles
Migration Cheat Sheet
Most Zod schemas translate cleanly to Valibot:
// Zod
const schema = z.object({
email: z.string().email(),
age: z.number().min(18),
});
// Valibot equivalent
const schema = object({
email: pipe(string(), email()),
age: pipe(number(), minValue(18)),
});
For AJV → Zod migration, the pattern change is more significant — you move from plain JSON objects to method-chained builders, but the concepts (required fields, string formats, number ranges) map 1:1.
Verdict
2026 defaults by use case:
| Scenario | Recommended |
|---|---|
| tRPC / Hono API validation | Zod |
| React Hook Form | Zod (hookform/resolvers) |
| High-volume Node.js API | AJV or TypeBox+AJV |
| OpenAPI / JSON Schema ecosystem | AJV |
| Next.js client-side forms | Valibot |
| Edge functions / Workers | Valibot |
| Cross-language schema sharing | AJV (JSON Schema) |
If you can only pick one and aren't sure: Zod for new TypeScript projects. The DX is unmatched, the ecosystem support is deep, and Zod v4's performance improvements have closed much of the gap with Valibot for most real-world form validation workloads.
Methodology
- Performance benchmarks from schema-benchmarks.dev and icebob/validator-benchmark (GitHub), March 2026
- Bundle sizes measured with esbuild on a simple object schema (3 string fields), March 2026
- npm download data from npmjs.com: AJV ~85M/week, Zod ~10M/week, Valibot ~3M/week
- TypeScript inference examples tested with TypeScript 5.6
Related: Zod v4 vs Valibot: TypeScript Validation 2026, ArkType vs Zod 2026, Best TypeScript Utility Types 2026. See also our full npm package comparison index.