Schema Design and Data Modeling

intermediate
14 min

Schema Design and Data Modeling

MongoDB will happily store whatever you throw at it, which means the responsibility for good structure moves from the database to you. The difference between a fast, maintainable MongoDB application and a slow, tangled one is almost always schema design. This CodeYourCraft lesson teaches the design mindset, the workload-first process, and the tools MongoDB gives you to keep data honest.

Design for Your Queries, Not Your Entities

Relational modeling starts from entities and normalizes them into tables. Document modeling starts from a different question: what does the application actually read and write, and how often? The guiding principle is that data that is accessed together should be stored together. If your product page always shows a product with its specs and top reviews, storing those in one document turns the hottest read in your app into a single document fetch.

Begin every design by listing your workload: the main screens and jobs, the queries behind them, their frequency, and whether they are read-heavy or write-heavy. Then shape documents so the most frequent operations touch the fewest documents.

A Worked Example: Blog Platform

Consider posts, authors, comments, and tags. A workload-first design might look like this:

javascript
// posts collection: one document renders the whole post page { _id: ObjectId('...'), title: 'Designing MongoDB Schemas', slug: 'designing-mongodb-schemas', author: { _id: ObjectId('...'), name: 'Sara Iyer' }, // denormalized subset tags: ['mongodb', 'database-design'], body: '...', commentCount: 128, recentComments: [ { user: 'dev_amit', text: 'Great write-up!', at: ISODate('...') } ] }

The author name is duplicated from the authors collection, a deliberate denormalization: post pages render without a join, and if the author renames, one updateMany fixes all their posts. Only recent comments are embedded; the full archive lives in a comments collection, keeping the post document small and bounded.

Denormalization and Its Price

Duplicating data optimizes reads at the cost of coordinated writes. Duplicate fields that are read constantly but change rarely, such as names, titles, and thumbnails. Avoid duplicating anything that changes often or must always be exactly consistent, such as account balances. When you do duplicate, write down where each copy lives so update code can keep them in sync.

Common Anti-Patterns

  • Unbounded arrays: embedding every comment or event into one document eventually hits the 16 MB cap and makes every read heavier. Bound embedded arrays or move items to their own collection.
  • Massive documents: storing rarely used blobs (full-resolution images, giant histories) inside hot documents wastes cache. Split cold data out.
  • Too many collections: creating a collection per user or per day multiplies indexes and management overhead; use a field to distinguish instead.
  • Treating MongoDB like SQL: fully normalizing everything and joining with $lookup on every read gives you the costs of both worlds and the benefits of neither.

Enforcing Structure with Schema Validation

Flexibility should be a choice, not an accident. JSON Schema validation rejects malformed writes at the database boundary:

javascript
db.createCollection('customers', { validator: { $jsonSchema: { bsonType: 'object', required: ['name', 'email'], properties: { name: { bsonType: 'string' }, email: { bsonType: 'string', pattern: '^.+@.+$' }, points: { bsonType: 'int', minimum: 0 } } } }, validationAction: 'error' })

Use validation for the invariants that must never break, while letting optional fields evolve freely.

Key Takeaways

  • Model around your workload: data accessed together should be stored together.
  • Denormalize read-heavy, rarely changing fields, and track every copy you create.
  • Keep arrays bounded and documents lean; split cold data into other collections.
  • Schema validation enforces critical invariants without giving up flexibility.
  • Revisit the schema as the workload evolves; migrations are normal, not failures.

The biggest single design decision, whether to embed related data or reference it, deserves its own lesson, and that is exactly what comes next.

Schema Design and Data Modeling - MongoDB | CodeYourCraft | CodeYourCraft