Zod vs class-validator for NestJS Validation (2026)
Table of Contents
class-validator is the NestJS default — it uses decorators on DTO classes and integrates with the built-in ValidationPipe. Zod works in NestJS via a custom pipe but requires more setup. For greenfield projects that prioritize TypeScript type inference and plain-object validation, Zod is worth the extra setup. For teams following NestJS conventions, class-validator fits naturally.
This guide covers both approaches with working code so you can make an informed decision.
NestJS Default: class-validator with ValidationPipe
The standard NestJS validation setup:
npm install class-validator class-transformer
// main.ts
app.useGlobalPipes(new ValidationPipe({ transform: true }));
// create-user.dto.ts
import { IsEmail, IsString, MinLength, IsOptional, IsNumber } from 'class-validator';
export class CreateUserDto {
@IsString()
@MinLength(2)
name: string;
@IsEmail()
email: string;
@IsNumber()
@IsOptional()
age?: number;
}
This is the NestJS-documented approach, and most NestJS tutorials use it. The decorators are readable and colocated with the DTO definition.
Using Zod in NestJS with a Custom Pipe
npm install zod
// zod-validation.pipe.ts
import { PipeTransform, BadRequestException } from '@nestjs/common';
import { ZodSchema } from 'zod';
export class ZodValidationPipe implements PipeTransform {
constructor(private schema: ZodSchema) {}
transform(value: unknown) {
const result = this.schema.safeParse(value);
if (!result.success) {
throw new BadRequestException(result.error.flatten().fieldErrors);
}
return result.data;
}
}
// users.controller.ts
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().optional()
});
@Post()
@UsePipes(new ZodValidationPipe(CreateUserSchema))
create(@Body() dto: z.infer<typeof CreateUserSchema>) {
return this.usersService.create(dto);
}
Sell Custom Apparel — We Handle Printing & Free Shipping
Side-by-Side Comparison
| Factor | class-validator | Zod |
|---|---|---|
| NestJS integration | Native (ValidationPipe) | Custom pipe needed |
| Syntax | Class decorators | Functional API |
| TypeScript inference | Requires separate interface | z.infer automatic |
| Plain object support | No (requires class instance) | Yes |
| Reuse across layers | Harder (class-specific) | Easy (schema = type) |
| Community | NestJS standard | Growing in NestJS |
| Testing | class-transformer required | Direct object testing |
When to Choose Each
Choose class-validator when:
- You are following the official NestJS documentation and patterns
- Your team is already familiar with it from other NestJS projects
- You want zero-friction integration with ValidationPipe
- Your codebase is already class-based throughout
Choose Zod when:
- You want automatic TypeScript type inference from your schemas
- You are also using Zod on the frontend and want to share schemas
- You prefer plain-object patterns over class instances
- You are building a monorepo where the same schema is used in multiple packages
To generate a base Zod schema from a sample request body, paste the JSON into the JSON to Zod converter.
Try It Free — No Signup Required
Runs 100% in your browser. No data is collected, stored, or sent anywhere.
Open Free JSON to Zod ConverterFrequently Asked Questions
Should I use Zod or class-validator in NestJS?
Both work. class-validator integrates natively with NestJS ValidationPipe and follows the official docs. Zod requires a custom pipe but provides better TypeScript inference and works with plain objects. For new projects, either is fine — pick based on your team's TypeScript preferences.
Can I use Zod with the NestJS ValidationPipe?
Not directly. NestJS ValidationPipe is built for class-validator. To use Zod, create a ZodValidationPipe class that implements PipeTransform and calls schema.safeParse() internally.
Can I mix Zod and class-validator in the same NestJS project?
Yes. You can use class-validator for most DTOs (via ValidationPipe) and Zod for specific cases where you need better inference or shared schemas. Apply the ZodValidationPipe per-route where needed.
How do I generate a Zod schema for a NestJS DTO?
Paste a sample request body JSON into the free converter at /developer-tools/json-to-zod/. Copy the generated schema, add NestJS-appropriate constraints (.email(), .min(), .optional()), and use it with the ZodValidationPipe.

