6.3 Schema Validation with JSON Schema

Key Takeaways

  • MongoDB provides server-side schema validation via '$jsonSchema', enforcing document structure, mandatory fields, and value ranges during writes.
  • The 'bsonType' keyword enforces strict BSON types ('string', 'int', 'long', 'double', 'decimal', 'objectId', 'date') beyond standard JSON primitives.
  • 'validationLevel' controls scope: 'strict' (default) evaluates all writes, while 'moderate' validates inserts and updates to valid docs while exempting legacy invalid docs.
  • 'validationAction' determines failure handling: 'error' (default) rejects the write with DocumentValidationFailure (Code 121), whereas 'warn' logs the violation to mongod.log.
  • Validation rules are modified dynamically via the 'collMod' command, and setting 'additionalProperties: false' requires explicitly declaring '_id' in properties.
Last updated: September 2026

6.3 Schema Validation with JSON Schema

While MongoDB is renowned for its flexible, dynamic document model, enterprise applications require robust data governance, type safety, and structural consistency. Rather than relying solely on client-side Object-Document Mappers (ODMs) like Mongoose or Spring Data—which can be bypassed by direct database connections or microservices written in different languages—MongoDB provides Server-Side Schema Validation.

Schema validation is defined at the collection level using the $jsonSchema operator. Validation rules are enforced natively by the mongod storage engine whenever an insertOne(), insertMany(), updateOne(), updateMany(), replaceOne(), or findAndModify() operation executes.


1. The $jsonSchema Validator Syntax

MongoDB supports the JSON Schema Draft 4 standard, extended with MongoDB-specific keywords—most notably bsonType.

+-----------------------------------------------------------------------------+
|                        $jsonSchema Core Keywords                            |
|                                                                             |
|  - bsonType             : Enforces specific BSON types ('string', 'int'...) |
|  - required             : Array of mandatory field names                    |
|  - properties           : Map defining validation rules for specific fields |
|  - additionalProperties : Boolean / Schema controlling undeclared fields    |
|  - enum                 : Array of permitted literal values                 |
|  - minimum / maximum    : Inclusive numeric boundary constraints            |
|  - pattern              : Regular expression string match                   |
|  - items                : Schema validator applied to array elements        |
|  - description          : Human-readable error/documentation string         |
+-----------------------------------------------------------------------------+

Standard BSON Type Identifiers (bsonType)

In JSON Schema, types are typically generic ("number", "string", "object"). In MongoDB $jsonSchema, developers can specify exact BSON type aliases:

  • "string"
  • "int" (32-bit signed integer)
  • "long" (64-bit signed integer)
  • "double" (64-bit IEEE floating-point)
  • "decimal" (128-bit decimal floating-point / Decimal128)
  • "bool"
  • "objectId"
  • "array"
  • "object"
  • "date"
  • "timestamp"
  • "null"

Exam Trap: In the MongoDB Shell (mongosh), writing { age: 30 } creates a 64-bit float (double) by default. If a $jsonSchema rule requires bsonType: "int", inserting { age: 30 } without explicit casting (such as NumberInt(30)) will fail schema validation! To allow any numeric type, pass an array of types: bsonType: ["int", "long", "double", "decimal"] or bsonType: "number".


2. Defining Schema Validation with db.createCollection()

When initializing a new collection, schema validation rules are supplied inside the options document via the validator parameter:

db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      title: "User Document Validation",
      required: [ "username", "email", "status", "role", "created_at" ],
      additionalProperties: true, // Allows unlisted optional fields
      properties: {
        _id: {
          bsonType: "objectId"
        },
        username: {
          bsonType: "string",
          minLength: 3,
          maxLength: 30,
          description: "'username' must be a string between 3 and 30 characters and is required"
        },
        email: {
          bsonType: "string",
          pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
          description: "'email' must match standard email regex format and is required"
        },
        status: {
          enum: [ "PENDING", "ACTIVE", "SUSPENDED", "ARCHIVED" ],
          description: "'status' can only be one of the enum values and is required"
        },
        role: {
          enum: [ "USER", "MANAGER", "ADMIN" ],
          description: "'role' must be USER, MANAGER, or ADMIN"
        },
        age: {
          bsonType: "int",
          minimum: 18,
          maximum: 120,
          description: "'age' must be an integer between 18 and 120"
        },
        created_at: {
          bsonType: "date",
          description: "'created_at' must be a BSON Date and is required"
        },
        tags: {
          bsonType: "array",
          minItems: 1,
          maxItems: 10,
          uniqueItems: true,
          items: {
            bsonType: "string"
          },
          description: "'tags' must be an array of up to 10 unique strings"
        },
        address: {
          bsonType: "object",
          required: [ "street", "city", "zip" ],
          properties: {
            street: { bsonType: "string" },
            city: { bsonType: "string" },
            zip: { bsonType: "string", pattern: "^[0-9]{5}(-[0-9]{4})?$" }
          }
        }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
});

3. Validation Levels: strict vs. moderate

The validationLevel option determines which write operations are subject to validation checks:

Validation LevelApplies to insert OperationsApplies to Updates on Valid DocumentsApplies to Updates on Existing Invalid Docs
strict (Default)EnforcedEnforcedEnforced (Update fails if doc remains invalid)
moderateEnforcedEnforcedSkipped (Allows updating legacy non-compliant docs)
offDisabledDisabledDisabled
+-----------------------------------------------------------------------------+
|                        validationLevel Execution Flow                       |
|                                                                             |
|  1. INCOMING INSERT:                                                        |
|     Both 'strict' and 'moderate' ALWAYS validate new documents.             |
|                                                                             |
|  2. INCOMING UPDATE:                                                        |
|     - Document ALREADY conforms to schema:                                  |
|       --> Both 'strict' and 'moderate' validate the modified document.      |
|                                                                             |
|     - Document was PREVIOUSLY NON-COMPLIANT (Legacy data before validator):|
|       --> 'strict': REJECTS the update unless the update fixes all errors.  |
|       --> 'moderate': PERMITS the update to proceed without error!          |
+-----------------------------------------------------------------------------+

When to Use moderate

When introducing schema validation to an existing production database containing legacy documents that violate the new rules, setting validationLevel: "moderate" allows application updates to existing legacy documents without breaking live services, while guaranteeing that all new inserts and updates to modern documents strictly adhere to the schema.


4. Validation Actions: error vs. warn

The validationAction option controls what action MongoDB takes when a write operation violates the validation rules:

Validation ActionBehavior on ViolationWrite Operation ResultLogging & Diagnostic Visibility
error (Default)Rejects write immediatelyThrows DocumentValidationFailure (Code 121)Write is aborted; nothing written to disk
warnAccepts write to storageWrite succeeds with acknowledgmentLogs validation violation warning to mongod.log

Production Migration Strategy with warn

When deploying a new schema validation rule to a mission-critical system, best practice follows a phased migration path:

  1. Deploy with validationAction: "warn".
  2. Monitor server diagnostic logs (mongod.log) for validation warning entries to identify misbehaving client services.
  3. Fix client-side data serialization bugs.
  4. Promote validationAction to "error" to enforce hard database-level rejection.

5. Modifying Existing Validators with collMod

Collections cannot be redefined with createCollection() once they exist. To update schema validators, change validation levels, or toggle validation actions on a live collection, use the administrative collMod (Collection Modify) command via db.runCommand().

Syntax for collMod

db.runCommand({
  collMod: "users", // Target collection name
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: [ "username", "email", "status", "tier" ], // Added 'tier' as required
      properties: {
        username: { bsonType: "string" },
        email: { bsonType: "string" },
        status: { enum: [ "ACTIVE", "INACTIVE" ] },
        tier: { enum: [ "BRONZE", "SILVER", "GOLD", "PLATINUM" ] }
      }
    }
  },
  validationLevel: "moderate",
  validationAction: "error"
});

Inspecting Active Collection Validation Rules

To inspect the active validator, validationLevel, and validationAction on a collection, query db.getCollectionInfos():

// In mongosh:
db.getCollectionInfos({ name: "users" });

// Returns:
[
  {
    name: "users",
    type: "collection",
    options: {
      validator: { $jsonSchema: { ... } },
      validationLevel: "moderate",
      validationAction: "error"
    },
    info: { readOnly: false }
  }
]

Completely Removing Validation from a Collection

To remove validation entirely, pass an empty object {} as the validator in collMod:

db.runCommand({
  collMod: "users",
  validator: {},
  validationLevel: "off"
});

6. Testing and Handling Validation Errors

When a write violates schema rules under validationAction: "error", MongoDB halts the write and returns an error payload with error code 121 (DocumentValidationFailure):

// Attempting an invalid insert (missing required 'email' and invalid 'status')
try {
  db.users.insertOne({
    username: "john_doe",
    status: "INVALID_STATUS", // Not in enum
    role: "USER",
    created_at: new Date()
  });
} catch (e) {
  console.error("Write failed:", e.message);
  // MongoServerError: Document failed validation
  // Error Code: 121 (DocumentValidationFailure)
}

The additionalProperties Keyword

  • additionalProperties: true (Default if omitted): Documents can contain arbitrary fields not declared in the properties map.
  • additionalProperties: false: Documents are strictly prohibited from containing any fields not explicitly listed in properties.

Exam Trap: When setting additionalProperties: false, you must include the _id field in the properties object (e.g., _id: { bsonType: "objectId" }). If _id is omitted from properties, every document insertion will fail validation because MongoDB drivers automatically inject _id before transmission!

Loading diagram...
MongoDB Write Pipeline Schema Validation Architecture
Test Your Knowledge

A collection has schema validation enabled with 'validationLevel: "moderate"' and 'validationAction: "error"'. The collection contains an existing legacy document that was inserted before validation was configured and does NOT conform to the schema. An application issues an 'updateOne()' command modifying a valid field on this legacy document. What is the result?

A
B
C
D
Test Your Knowledge

A database administrator configures a collection with 'validationAction: "warn"'. When an application attempts to insert a document that violates the required fields defined in '$jsonSchema', what occurs?

A
B
C
D
Test Your Knowledge

Which MongoDB administrative command is used to add or modify schema validation rules on an existing collection without dropping it?

A
B
C
D
Test Your Knowledge

A collection validator defines a rule requiring: 'age: { bsonType: "int", minimum: 21 }'. When executing an insert in the MongoDB Shell using 'db.users.insertOne({ age: 25 })', the write fails with a DocumentValidationFailure error. Why did this validation failure occur?

A
B
C
D