Defines the shape of data to be inserted into the database - can be used to validate API requests.
import { pgTable, text, integer } from 'drizzle-orm/pg-core';import { createInsertSchema } from 'drizzle-zod';const users = pgTable('users', { id: integer().generatedAlwaysAsIdentity().primaryKey(), name: text().notNull(), age: integer().notNull()const userInsertSchema = createInsertSchema(users);const user = { name: 'John' };const parsed: { name: string, age: number } = userInsertSchema.parse(user); // Error: `age` is not definedconst user = { name: 'Jane', age: 30 };const parsed: { name: string, age: number
} = userInsertSchema.parse(user); // Will parse successfullyawait db.insert(users).values(parsed);
Update schema
Defines the shape of data to be updated in the database - can be used to validate API requests.
import { pgTable, text, integer } from 'drizzle-orm/pg-core';import { createUpdateSchema } from 'drizzle-zod';const users = pgTable('users', { id: integer().generatedAlwaysAsIdentity().primaryKey(), name: text().notNull(), age: integer().notNull()const userUpdateSchema = createUpdateSchema(users);const user = { id: 5, name: 'John' };const parsed: { name?: string | undefined, age?: number | undefined } = userUpdateSchema.parse(user); // Error: `id` is a generated column, it can't be updatedconst user = { age: 35 };const parsed: { name?: string | undefined, age?: number | undefined } = userUpdateSchema.parse(user); // Will parse successfullyawait db.update(users).set(parsed).where(eq(users.name, 'Jane'));
Refinements
Each create schema function accepts an additional optional parameter that you can used to extend, modify or completely overwite a field’s schema. Defining a callback function will extend or modify while providing a Zod schema will overwrite it.
import { pgTable, text, integer, json } from 'drizzle-orm/pg-core';import { createSelectSchema } from 'drizzle-zod';import { z } from 'zod/v4';const users = pgTable('users', { id: integer().primaryKey(), name: text().notNull(), bio: text(),
preferences: json()const userSelectSchema = createSelectSchema(users, { name: (schema) => schema.max(20), // Extends schema bio: (schema) => schema.max(1000), // Extends schema before becoming nullable/optional preferences: z.object({ theme: z.string() }) // Overwrites the field, including its nullabilityconst parsed: { id: number; name: string, bio?: string | undefined; preferences: { theme: string;} = userSelectSchema.parse(...);
Factory functions
For more advanced use cases, you can use the
createSchemaFactory
function.
Use case: Using an extended Zod instance
import { pgTable, text, integer } from 'drizzle-orm/pg-core';import { createSchemaFactory } from 'drizzle-zod';import { z } from '@hono/zod-openapi'; // Extended Zod instanceconst users = pgTable('users', { id: integer().generatedAlwaysAsIdentity().primaryKey(), name: text().notNull(), age: integer().notNull()const { createInsertSchema } = createSchemaFactory({ zodInstance: z });const userInsertSchema = createInsertSchema(users, { // We can now use the extended instance name: (schema) => schema.openapi({ example: 'John' })
Use case: Type coercion
import { pgTable, timestamp } from 'drizzle-orm/pg-core';import { createSchemaFactory } from 'drizzle-zod';import { z } from 'zod/v4';const users = pgTable('users', { ..., createdAt: timestamp().notNull()const { createInsertSchema } = createSchemaFactory({ // This configuration will only coerce dates. Set `coerce` to `true` to coerce all data types or specify others coerce: { date: trueconst userInsertSchema = createInsertSchema(users);// The above is the same as this:const userInsertSchema = z.object({ ..., createdAt: z.coerce.date()