MongoDBSchema Validation (JSON Schema)

Schema Validation

MongoDB is schemaless by default, but that doesn't mean you should give up on data integrity. Schema validation lets you attach a JSON Schema to a collection so the server itself rejects documents that don't match — required fields, types, ranges, and patterns are enforced at the database layer, not just in application code.

Adding a Validator on createCollection

JS
db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["email", "name", "age"],
      properties: {
        email: {
          bsonType: "string",
          pattern: "^\S+@\S+\.\S+$",
          description: "must be a valid email address and is required"
        },
        name: {
          bsonType: "string",
          minLength: 1,
          description: "must be a non-empty string and is required"
        },
        age: {
          bsonType: "int",
          minimum: 0,
          maximum: 150,
          description: "must be an integer between 0 and 150"
        }
      }
    }
  }
})
Adding or Changing a Validator on an Existing Collection

JS
db.runCommand({
  collMod: "users",
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["email", "name"],
      properties: {
        email: { bsonType: "string" },
        name: { bsonType: "string" }
      }
    }
  },
  validationLevel: "moderate",
  validationAction: "warn"
})
$jsonSchema Syntax Building Blocks

Keyword

Purpose

bsonType

Restrict the BSON type: string, int, long, double, bool, date, objectId, array, object, null

required

Array of field names that must be present

properties

Per-field schema rules, keyed by field name

enum

Value must be one of a fixed list

minimum / maximum

Numeric range bounds

minLength / maxLength

String length bounds

pattern

Regular expression the string must match

items

Schema applied to every element of an array field

additionalProperties

Set to false to reject unknown fields entirely

Validating an Enum and a Range

JS
db.createCollection("orders", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["status", "total"],
      properties: {
        status: {
          enum: ["pending", "processing", "shipped", "delivered", "cancelled"],
          description: "must be one of the allowed statuses and is required"
        },
        total: {
          bsonType: "double",
          minimum: 0,
          description: "must be a non-negative number and is required"
        },
        items: {
          bsonType: "array",
          minItems: 1,
          items: {
            bsonType: "object",
            required: ["sku", "qty"],
            properties: {
              sku: { bsonType: "string" },
              qty: { bsonType: "int", minimum: 1 }
            }
          }
        }
      }
    }
  }
})
validationLevel

Controls which writes get checked against the schema.

Level

Behavior

strict (default)

Applies the validator to all inserts and all updates

moderate

Applies the validator to inserts, and to updates only on documents that already match the schema — lets pre-existing non-conforming documents be edited without being blocked

off

Disables validation entirely (validator stays attached but unused)

validationAction

Action

Behavior

error (default)

Rejects the write, throws a validation error

warn

Allows the write, but logs a warning to the server log

Tip
Rolling out validation on an existing collection with unknown-quality data? Start with validationLevel: "moderate" and validationAction: "warn" to see how many documents would fail, then tighten to strict/error once the data is clean.
What a Validation Failure Looks Like

JS
db.users.insertOne({ name: "Bob" })  // missing required "email"
MongoServerError: Document failed validation
Additional Information:
  Details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      { operatorName: 'required', specifiedAs: { required: [ 'email', 'name', 'age' ] },
        missingProperties: [ 'email', 'age' ] }
    ]
  }
Checking an Existing Validator

JS
db.getCollectionInfos({ name: "users" })[0].options.validator
Removing Validation

JS
db.runCommand({ collMod: "users", validator: {}, validationLevel: "off" })
Warning
Schema validation is not a replacement for application-level validation and error handling — it's a last line of defense at the database layer. Bad writes should ideally be caught in your application before they ever reach MongoDB; validation exists to catch what slips through (a bug, a script, a different service).
Bonus: bsonType vs type

$jsonSchema is standard JSON Schema, but MongoDB extends it with bsonType, which understands BSON-specific types (objectId, date, decimal, long) that plain JSON Schema's type keyword doesn't have. Prefer bsonType for anything beyond basic string/number/bool/array/object.

  • Use $jsonSchema for structural, type, and range validation at write time.

  • Use validationLevel: "moderate" when migrating an existing collection with legacy documents.

  • Use validationAction: "warn" to dry-run a stricter schema before enforcing it.

  • Combine with application-side validation (Mongoose schemas, Joi/Zod, etc.) — validators are a safety net, not the only layer.