---
title: Use Schema Validation
impact: MEDIUM
impactDescription: "Prevents invalid data at database level, catches bugs before production corruption"
tags: schema, validation, json-schema, data-integrity, fundamentals
---

## Use Schema Validation

**Enforce document structure with MongoDB's built-in JSON Schema validation.** Catch invalid data before it corrupts your database, not after you've shipped 10,000 malformed documents to production. Schema validation is your last line of defense when application bugs slip through.

**Incorrect (no validation):**

Without validation, any document shape is accepted: an `email` field can contain a non-email string, an `age` field can hold a string instead of a number, and required fields like `email` can be omitted entirely. These invalid documents are discovered only when downstream consumers crash or return wrong data — often months later.

**Correct (schema validation):**

```javascript
// Create collection with validation rules
db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["email", "name"],
      properties: {
        email: {
          bsonType: "string",
          pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
          description: "must be a valid email address"
        },
        name: {
          bsonType: "string",
          minLength: 1,
          maxLength: 100,
          description: "must be 1-100 characters"
        },
        age: {
          bsonType: "int",
          minimum: 0,
          maximum: 150,
          description: "must be integer 0-150"
        },
        status: {
          enum: ["active", "inactive", "pending"],
          description: "must be one of: active, inactive, pending"
        },
        addresses: {
          bsonType: "array",
          maxItems: 10,  // Prevent unbounded arrays
          items: {
            bsonType: "object",
            required: ["city"],
            properties: {
              street: { bsonType: "string" },
              city: { bsonType: "string" },
              zip: { bsonType: "string", pattern: "^[0-9]{5}$" }
            }
          }
        }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
})

// Invalid inserts now fail immediately with clear error
db.users.insertOne({ email: "not-an-email" })
// Error: Document failed validation:
// "email" does not match pattern, "name" is required
```

**Validation levels and actions:**

| validationLevel | Behavior |
|-----------------|----------|
| `strict` | Validate ALL inserts and updates (default, recommended) |
| `moderate` | Only validate documents that already match schema |

| validationAction | Behavior |
|------------------|----------|
| `error` | Reject invalid documents (default, recommended) |
| `warn` | Allow but log warning (use during migration only) |

**Add validation to existing collection:**

```javascript
// Start with moderate + warn to discover violations
db.runCommand({
  collMod: "users",
  validator: { $jsonSchema: {...} },
  validationLevel: "moderate",  // Don't break existing invalid docs
  validationAction: "warn"       // Log violations, don't block
})

// Check for violations using the actual validator shape
const info = db.getCollectionInfos({ name: "users" })[0]
const validator = info?.options?.validator
db.users.find({ $nor: [validator] })

// Then switch to strict + error
db.runCommand({
  collMod: "users",
  validationLevel: "strict",
  validationAction: "error"
})
```

**When NOT to use this pattern:**

- **Rapid prototyping**: Skip validation during early development, add before production.
- **Schema-per-document designs**: Some collections intentionally store varied document shapes.
- **Log/event collections**: High-write collections where validation overhead matters.

## Verify with

```javascript
// Read current validator and validation settings
const info = db.getCollectionInfos({ name: "users" })[0]
printjson({
  validationLevel: info?.options?.validationLevel,
  validationAction: info?.options?.validationAction,
  validator: info?.options?.validator
})

// Primary compliance check: find documents that do NOT match validator
const validator = info?.options?.validator
db.users.find({ $nor: [validator] })
```

Reference: [Schema Validation](https://mongodb.com/docs/manual/core/schema-validation/)
