Enforcing Document Shape in MongoDB with JSON Schema Validation
Learn how to add a JSON Schema validator to a MongoDB collection, see a complete example of required and optional fields, and understand the limits and common pitfalls of this feature.
29 Jul 2026, 14:11 UTC

Useful answer: enforce document shape with JSON Schema
MongoDB can automatically reject inserts or updates that do not conform to a predefined document structure by attaching a JSON Schema validator to a collection. The validator runs on the server for every write operation; if a document fails validation, the operation returns a WriteError with code 121 (Document failed validation) and is aborted unless you switch the validator to warning mode. This gives you a lightweight way to guarantee required fields, data types, and basic constraints without application‑level code.
How validation works: server‑side check
When you create or modify a collection you can supply a validator document that contains a \$jsonSchema object. MongoDB evaluates the schema against each incoming document using the same rules as the JSON Schema specification (draft‑4). The check happens after any write concern is applied but before the data is persisted. If validation fails, the write is rolled back and the error is returned to the client. If you set validationAction: warn, the write succeeds but a warning is logged.
Worked example: creating a validated users collection
The following mongo shell snippet creates a collection named users that requires a username string, an email string matching a simple pattern, and an optional age integer that must be zero or greater. Additional fields are allowed because we do not set additionalProperties: false.
use mydb
db.createCollection("users", {
validator: {
\$jsonSchema: {
bsonType: "object",
required: ["username", "email"],
properties: {
username: { bsonType: "string" },
email: {
bsonType: "string",
pattern: "^[^@]+@[^@]+\\\\.[^@]+$"
},
age: {
bsonType: "int",
minimum: 0
}
}
}
},
validationLevel: "strict", // default, validates inserts and updates
validationAction: "error" // default, reject invalid documents
})
After running this command, the collection exists and any write to users will be checked against the schema.
Testing validation: successful insert and failing insert
Insert a document that satisfies all constraints:
db.users.insertOne({
username: "alice",
email: "alice@example.com",
age: 30
})
Expected result: the insert is acknowledged (acknowledged: true) and the document is stored.
Now insert a document that violates the required email field:
db.users.insertOne({
username: "bob",
age: -5
})
Expected result: the operation fails with a WriteError similar to:
WriteError({
code: 121,
errmsg: "Document failed validation",
...
})
The write is not persisted; you can confirm by counting documents:
db.users.countDocuments({}) // returns 1 (only Alice's record)
Changing validation action to warn
If you prefer to allow non‑conforming writes while still being alerted, update the validator to use warning mode:
db.runCommand({
collMod: "users",
validator: {
\$jsonSchema: {
bsonType: "object",
required: ["username", "email"],
properties: {
username: { bsonType: "string" },
email: { bsonType: "string", pattern: "^[^@]+@[^@]+\\\\.[^@]+$" },
age: { bsonType: "int", minimum: 0 }
}
}
},
validationLevel: "strict",
validationAction: "warn" // changed from error to warn
})
Repeating the invalid insert now succeeds, but the MongoDB log contains a warning line such as:
[conn1] WARN: Document would fail validation: { username: "bob", age: -5 }
You can verify the change by checking the collection options:
db.getCollectionInfos({ name: "users" })[0].options
The output will show validationAction: "warn".
Version requirements and checking
JSON Schema validation was introduced in MongoDB 3.6. To ensure your deployment supports it, run:
db.version()
The output must be 3.6 or higher. Older versions only support the legacy \$operator style validator, which lacks the full JSON Schema feature set.
Limits and common mistakes
- Existing documents are not validated retroactively. Changing the validator on a collection with existing data does not automatically check those documents. Invalid data that was inserted before the validator change will remain unless you explicitly run a validation script or re‑insert the documents.
- Overly strict schemas break flexible applications. Setting
additionalProperties: falseforbids any field not listed inproperties. If your application relies on adding ad‑hoc fields for feature flags or temporary data, writes will start failing with code 121 after you enable this restriction. - No JavaScript or
\$wherein schemas. The JSON Schema validator does not evaluate JavaScript expressions; you cannot use\$whereor custom JS functions inside the\$jsonSchemaobject. For complex conditional logic you must rely on\$exprwithin the schema, which supports a limited set of aggregation expressions. - Performance impact. Validation adds CPU overhead on the mongod process for every write. In high‑throughput workloads you should benchmark the impact and consider whether validation is needed at the database level or can be enforced in the application layer.
Practical way to check the result
After any insert or update, inspect the WriteResult object. If writeResult.writeError is present and its code equals 121, validation rejected the document. In warning mode, writeResult.writeError will be absent, but you can look for a warning message in the server log (e.g., via mongod.log or the diagnostic data interface).
By following the steps above you can add a reliable JSON Schema validator to a MongoDB collection, test both success and failure paths, and understand the operational limits that often tripped up teams adopting this feature.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.