AJV vs Zod vs Valibot: Speed, Bundle Size & TypeScript (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.
Compare AJV and Zod package health on PkgPulse.
See the live comparison
View ajv vs. zod on PkgPulse →