Zod v4 is a major overhaul of the most popular TypeScript schema validation library — delivering 14x faster string parsing, a 57% smaller core bundle, and a completely reworked API for format validation. Most codebases can migrate in under a day using the official codemod, but there are real breaking changes that will catch you off guard if you skip the changelog.

What Is Zod v4 and Why the Major Version Bump?

Zod v4 is a ground-up rewrite of Zod’s internal architecture, released by Colin McDonnell in mid-2025 after two years of development driven by feedback from Zod v3’s performance and bundle size limitations. With over 42,835 GitHub stars and 102 million weekly npm downloads, Zod is the de facto TypeScript runtime validation standard — and v4 is the release that finally addresses the criticisms Valibot raised in 2023. The major version bump is justified: v4 ships real breaking changes to string format methods, object strictness options, and error handling. But beyond compatibility breaks, v4 introduces architectural changes — a new zod/v4/core sub-package, the @zod/mini tree-shakable distribution, a metadata registry system, and first-class JSON Schema conversion — that change what you can build with Zod. This isn’t just a performance patch; it’s a new foundation for the library’s next five years.

Why the Breaking Changes Were Necessary

The Zod v3 API accumulated technical debt around how string format validators were attached to the z.string() chain. Methods like .email(), .uuid(), .url(), and .ip() were implemented as string refinements, which blocked tree-shaking and forced all format logic into the core bundle even for schemas that never use email validation. Moving these to top-level functions (z.email(), z.uuid()) was the only architecturally sound path to enabling the @zod/mini 1.9 KB distribution.

Performance Improvements — 14x Faster Parsing and a 57% Smaller Bundle

Zod v4 is dramatically faster than v3 across all primitive types: 14x faster string parsing, 7x faster array parsing, and 6.5x faster object parsing, according to official benchmarks from the Zod v4 release page. On a realistic 50+ field schema parsing 1,000 objects, the improvement reaches 100x — dropping from 480ms in v3 to 4.8ms in v4. The core bundle is 57% smaller (2.3x), and TypeScript compile-time performance improves by up to 10x on large codebases. These numbers come from a complete rewrite of the parsing engine, which eliminated redundant type-checking layers, replaced recursive traversal with iterative loops, and pushed format validation out of the hot path. For most production applications, the cold-start and hot-path latency improvements will be noticeable immediately after upgrading. The smaller bundle also means less JavaScript for browsers to parse and execute, directly improving frontend performance metrics.

What Drives the Speed Gains

Three architectural decisions explain the performance jump:

  1. Eliminated double validation: v3 ran type checks twice in some paths; v4 does a single pass.
  2. Iterative instead of recursive: deeply nested schemas no longer risk stack overflows, and iterative traversal is faster in V8.
  3. Lazy format validation: z.string() no longer bundles email/url/uuid logic unless you explicitly import z.email().

Breaking Changes You Must Know Before Migrating

Zod v4 ships seven categories of breaking changes that will cause runtime errors or type errors if not addressed. The most impactful changes are: string format methods removed from z.string() chain, object strictness helpers deprecated, and ZodError constructor unified. Before touching your codebase, run npx zod-v3-to-v4 to catch the machine-fixable issues automatically.

String format methods moved to top-level functions:

// Zod v3
const emailSchema = z.string().email();
const urlSchema = z.string().url();
const uuidSchema = z.string().uuid();

// Zod v4
const emailSchema = z.email();
const urlSchema = z.url();
const uuidSchema = z.uuid();

Object strictness methods deprecated:

// Zod v3
const schema = z.object({ name: z.string() }).strict();
const schema2 = z.object({ name: z.string() }).passthrough();

// Zod v4
const schema = z.strictObject({ name: z.string() });
const schema2 = z.looseObject({ name: z.string() });

Error handling unified — single parameter for custom errors:

// Zod v3
z.string().min(3, { message: "Too short" });

// Zod v4
z.string().min(3, "Too short"); // string shorthand works
z.string().min(3, { error: "Too short" }); // 'message' → 'error'

z.discriminatedUnion() requires literal discriminators — computed or template literal discriminators from v3 will need refactoring.

ZodError.issues path format changed for nested arrays — update any custom error display logic that walks issue paths.

Breaking Change Impact by Project Type

Project TypeMost-Affected APIsRisk Level
Form validation (react-hook-form).email(), .url(), error messagesMedium
API validation (Express/Fastify).strict(), discriminatedUnionMedium
OpenAPI/tRPC schemasNearly all, but codemod covers mostLow-Medium
CLI toolsObject strictnessLow
Frontend-only (switching to @zod/mini)Full API surfaceHigh

New Features in Zod v4 — What You Actually Gain

Zod v4 adds capabilities that were impossible or impractical in v3: template literal type schemas, bidirectional JSON Schema conversion, a metadata registry, prettified error output, and the @zod/mini lightweight distribution. Template literal schemas (z.templateLiteral) let you validate strings like "event:${string}" with full TypeScript type inference — a feature previously only available in libraries like ArkType. JSON Schema conversion (z.toJSONSchema() / z.fromJSONSchema()) enables Zod to serve as the source of truth for OpenAPI specs without a separate schema definition layer. The metadata system (z.globalRegistry) lets you attach arbitrary metadata — descriptions, examples, deprecation flags — to any schema and access it at runtime. These aren’t minor additions; they close the gap between Zod and more specialized validation tools for API contract workflows.

New Error Formatting API

// Prettified errors — human-readable output for debugging
const result = z.object({ name: z.string(), age: z.number() }).safeParse({ name: 123, age: "old" });
if (!result.success) {
  console.log(z.prettifyError(result.error));
  // ✕ name: Expected string, received number
  // ✕ age: Expected number, received string
}

Template Literal Types

// Match "event:click", "event:hover", etc. with full type safety
const eventSchema = z.templateLiteral(["event:", z.string()]);
type Event = z.infer<typeof eventSchema>; // `event:${string}`

JSON Schema Round-Trip

import { z } from "zod";

const userSchema = z.object({
  id: z.uuid(),
  email: z.email(),
  age: z.number().int().min(0).max(150)
});

const jsonSchema = z.toJSONSchema(userSchema);
// { type: "object", properties: { id: { type: "string", format: "uuid" }, ... } }

// And back
const recovered = z.fromJSONSchema(jsonSchema);

@zod/mini — The Lightweight 1.9 KB Gzipped Distribution

@zod/mini is a separate npm package providing a tree-shakable subset of Zod v4 that weighs approximately 1.9 KB gzipped — compared to the full Zod v4 core which, while 57% smaller than v3, still ships more validation infrastructure than frontend bundles typically need. The package shares internal implementation with Zod v4 via the zod/v4/core sub-package, so it’s not a fork — schemas created with @zod/mini are fully compatible with Zod v4 schemas at the type level. The API difference is that @zod/mini replaces method-chaining refinements with standalone function wrappers: instead of z.string().min(3), you write z.string(z.minLength(3)). This change is what enables proper tree-shaking in bundlers, since each validation function is a discrete import that dead-code elimination can remove. For frontend applications that currently import the full Zod package just for form validation, switching to @zod/mini can meaningfully reduce bundle sizes.

@zod/mini API Pattern

import { z } from "@zod/mini";

// @zod/mini uses function composition instead of method chaining
const emailSchema = z.string(z.email(), z.maxLength(100));
const userSchema = z.object({
  email: emailSchema,
  age: z.number(z.int(), z.gte(0), z.lte(150))
});

Zod vs @zod/mini vs Valibot Bundle Size

LibraryBundle (gzipped)API StyleTypeScript Inference
Zod v3~14 KBMethod chainFull
Zod v4 core~6 KBMethod chainFull
@zod/mini~1.9 KBFunction compositionFull
Valibot (simple form)~1.4 KBFunction compositionFull

Step-by-Step Migration Guide from Zod v3 to v4

Migrating from Zod v3 to v4 takes most projects under a day. The recommended sequence is: run the codemod first, fix TypeScript errors, then test your error handling paths. Start by installing Zod v4 — it’s still published to the zod package, so npm install zod@^4.0.0 is the only installation step. The codemod handles the highest-volume changes (string format methods, object strictness methods) automatically. Manual work is limited to: custom error message keys (messageerror), any code that directly constructs ZodError objects, and custom discriminated union patterns that relied on non-literal discriminators.

Step 1 — Update the package:

npm install zod@^4.0.0
# or
yarn add zod@^4.0.0
# or
pnpm add zod@^4.0.0

Step 2 — Run the codemod:

npx zod-v3-to-v4

Step 3 — Fix remaining TypeScript errors:

After the codemod, run tsc --noEmit and address any remaining type errors. Common remaining issues:

  • Custom ZodError construction — update to new constructor signature
  • z.discriminatedUnion() with non-literal discriminators — replace with union + refinement
  • .superRefine() callback signature changes — second parameter is now a context object

Step 4 — Update error message keys:

// Search-replace: message: → error: in Zod option objects
// Before
z.string().min(1, { message: "Required" })
// After
z.string().min(1, { error: "Required" })

Step 5 — Test error paths:

Run your form submission tests and API validation tests with invalid inputs. Zod v4 formats errors differently in some edge cases — snapshot tests on error shapes may need updating.

Using the zod-v3-to-v4 Automated Codemod

The zod-v3-to-v4 codemod is the fastest path through the mechanical parts of the Zod v4 migration. It uses jscodeshift to perform AST-level transforms — not regex substitution — so it handles complex cases like chained method calls inside ternaries, destructured schema assignments, and re-exported schemas correctly. Run it with npx zod-v3-to-v4 from your project root; it automatically scans src/ and lib/ directories. The --dry-run flag prints what would change without modifying files, useful for reviewing scope before committing. The codemod covers: .email()z.email(), .url()z.url(), .uuid()z.uuid(), .ip()z.ip(), .cuid()z.cuid(), .nanoid()z.nanoid(), .strict()z.strictObject(), .passthrough()z.looseObject(), and .strip()z.object(). It does NOT cover: messageerror key renames in option objects, discriminated union discriminator changes, or custom error class construction.

# Dry run first
npx zod-v3-to-v4 --dry-run

# Apply to src directory
npx zod-v3-to-v4 src/

# Apply to all TypeScript files in project
npx zod-v3-to-v4 --extensions=ts,tsx

What the Codemod Transforms (and What It Doesn’t)

TransformCodemod HandlesManual Required
.email()z.email()YesNo
.url()z.url()YesNo
.uuid()z.uuid()YesNo
.strict()z.strictObject()YesNo
.passthrough()z.looseObject()YesNo
message:error: in optionsNoYes
Discriminated union discriminatorsNoYes
ZodError constructor changesNoYes

Zod v4 vs Valibot and ArkType — Which Should You Choose?

Zod v4 is the right choice for most TypeScript projects in 2026, but it’s not the universal answer. Valibot remains meaningfully smaller for simple frontend schemas — a basic login form validation with Valibot is still ~90% smaller than Zod standard and ~73% smaller than Zod Mini, according to benchmarks from pkgpulse.com. ArkType offers the most advanced type inference in the ecosystem, supporting runtime-defined types with TypeScript-level fidelity that Zod’s structural approach can’t match. The practical decision comes down to three variables: bundle budget, ecosystem integration (tRPC, react-hook-form, Prisma, OpenAPI generators all have Zod adapters), and team familiarity. For any project already using Zod v3, upgrading to v4 is the obvious call. For greenfield frontend-only projects with strict bundle constraints, Valibot is worth evaluating. For complex domain type modeling where correctness matters more than ecosystem breadth, ArkType is the specialist choice.

Feature Comparison 2026

FeatureZod v4@zod/miniValibotArkType
Bundle size (gzipped)~6 KB~1.9 KB~1.4 KB~5 KB
Method chainingYesNoNoNo
JSON Schema outputBuilt-inBuilt-inPluginPlugin
Template literal typesYesYesNoYes
tRPC integrationNativePartialVia adapterVia adapter
TypeScript inference qualityExcellentExcellentExcellentBest-in-class
Codemod availablev3→v4

Should You Upgrade Now? — Practical Decision Framework

Upgrading to Zod v4 makes sense for the vast majority of Zod v3 users, but the timing depends on your dependency chain. As of June 2026, most major Zod consumers — tRPC, Prisma, react-hook-form resolvers, and popular OpenAPI generators — have released Zod v4 compatible versions. If you’re on a well-maintained dependency stack and not on an extremely old Node.js version (Zod v4 requires Node 16+), the upgrade path is low-risk. The main reason to delay is if your project has deep integrations with third-party libraries that haven’t yet published Zod v4 support — check their issue trackers before upgrading. The performance gains are real and not marginal: if you’re doing server-side validation on high-traffic routes, the 7–14x speedup translates directly to lower latency and reduced compute costs. For frontend projects, the smaller bundle is valuable even before reaching @zod/mini. The breaking changes are real but manageable — run the codemod, budget two to four hours for manual fixes, and test your error handling paths.

Upgrade Decision Matrix

Your SituationRecommendation
Zod v3 on active project, no unusual dependenciesUpgrade now
Zod v3 on project with custom ZodError handlingUpgrade, budget 4h for manual work
Zod v3 with niche third-party Zod adaptersCheck adapter compatibility first
New project starting freshUse Zod v4 from day one
Frontend-only, bundle size criticalEvaluate @zod/mini or Valibot
Node 14 or earlierStay on v3 or upgrade Node first

FAQ

Q: Is Zod v4 backward-compatible with Zod v3 schemas?

No, Zod v4 has real breaking changes. The most common are: string format methods (.email(), .url(), .uuid()) moved to top-level functions, object strictness helpers (.strict(), .passthrough()) renamed to z.strictObject() / z.looseObject(), and error option keys changed from message to error. The official codemod (npx zod-v3-to-v4) handles the high-volume transforms automatically, but some manual work remains.

Q: Do I need to rewrite my schemas for @zod/mini?

Yes, @zod/mini uses a different API style — function composition instead of method chaining. You cannot simply swap the import; you need to rewrite method chains like z.string().min(3).email() to the function composition equivalent z.string(z.minLength(3), z.email()). Consider @zod/mini only if you’re starting a new project or doing a purposeful frontend bundle optimization pass.

Q: Does Zod v4 work with tRPC?

Yes, as of tRPC v11 (released Q4 2025), Zod v4 is fully supported. If you’re on an older tRPC version, upgrade tRPC alongside Zod.

Q: How long does migration from Zod v3 to v4 take?

Most projects take two to eight hours. Run the codemod first (30 minutes), then address TypeScript errors (tsc --noEmit), then run your test suite. The main time sinks are: custom error message handling that used { message: "..." } syntax (now { error: "..." }), any code that directly instantiates ZodError, and discriminated union schemas with non-literal discriminators.

Q: Is Zod v4 faster for all schema types?

The published benchmarks show 14x faster string parsing, 7x faster array parsing, and 6.5x faster object parsing. These are best-case numbers; real-world gains depend on schema complexity and input characteristics. Schemas with many z.refine() calls or async validators will see smaller gains since those paths weren’t the primary optimization target. For typical REST API request validation with simple object/string/number types, expect gains in the 4–10x range in practice.