MongoDB with Zod as the single source of truth
The Mongoose alternative built on Zod and the official MongoDB® driver. One schema validates every write, types every read and defines what each endpoint accepts.
npm install mongozodimport { ObjectId } from 'mongodb'
import { mongozod } from 'mongozod'
import * as mz from 'mongozod/mzod'
import * as z from 'zod'
const postSchema = z.object({
_id: mz.objectId()
.default(() => new ObjectId()),
title: z.string()
.min(1),
status: z.enum(['draft', 'published'])
.default('draft'),
tags: z.string()
.array()
.default([])
})
const PostsModel = mongozod({
collection: 'posts',
db,
schema: postSchema
})
// Validated with the schema: _id, status and tags come from their defaults
const { document: post } = await PostsModel.insertOne({ title: 'Hello, MongoDB' })
// Typed by the schema: a status that is not in the enum does not compile
await PostsModel.updateOne({ _id: post._id }, { $set: { status: 'published' } })
// A projection narrows the result: Array<{ _id: ObjectId; title: string }>
const titles = await PostsModel.find({ tags: 'mongodb' }, { projection: { title: 1 } })
// An endpoint takes MongoDB syntax, limited to what it declares
const listPostsInput = z.object({
filter: mz
.filter(postSchema, {
status: ['$eq'],
tags: ['$in']
})
.default({})
})Every write validated
Inserts, replacements and each value of every update operator, refinements included. An upsert validates the document it would insert.
Strict types
Filters, updates, projections and sorts with every MongoDB operator and dotted paths, checked against the schema.
What you used in Mongoose
Populate, virtuals, timestamps, discriminators, indexes, $jsonSchema validation and plugins, such as soft delete.
Endpoint inputs
Zod schemas that accept MongoDB syntax from clients, limited to what each endpoint declares, and BSON field types.
The official driver
Its names, options and results, and the driver itself for everything else. Mongoose can share the connection while you migrate.
Made for agents
The docs ship in the package at the installed version, and every page is Markdown at its .md URL, with llms.txt.