Back to Blogs

MongoDB Schema Design: Building Scalable Data Models for SaaS ๐Ÿ—„๏ธMongoDB Schema Design: Building Scalable Data Models for SaaS ๐Ÿ—„๏ธ

9 months ago
MongoDB Schema Design: Building Scalable Data Models for SaaS ๐Ÿ—„๏ธ

MongoDB Schema Design for SaaS ๐Ÿ—„๏ธ

"Schema-less" is a myth in production. If you don't design your MongoDB schema with access patterns in mind, your SaaS will crawl as it scales.

The Problem I Faced

I built a project management tool where I embedded every "Comment" inside the "Task" document. It was great... until a task had 5,000 comments. The document size limit hit, and pulling a task meant pulling megabytes of text data I didn't need.

Understanding Embedding vs. Referencing

  • Embedding: Good for small, strictly related data that is always accessed together (e.g., User Settings inside User).
  • Referencing: Good for unbounded lists or data accessed independently (e.g., Comments on a Post).

Code Example 1: The "Referencing" Pattern (Scalable)

ts
// User Model { _id: ObjectId("..."), name: "Zahid", email: "zahid@example.com" } // Project Model { _id: ObjectId("..."), title: "Website Redesign", ownerId: ObjectId("...") // Reference to User } // Task Model { _id: ObjectId("..."), projectId: ObjectId("..."), // Reference to Project title: "Fix Homepage CSS", assignedTo: [ObjectId("...")] // Array of User References }

Code Example 2: Using Mongoose with Next.js

ts
import mongoose, { Schema } from 'mongoose'; const TaskSchema = new Schema({ title: String, project: { type: Schema.Types.ObjectId, ref: 'Project' }, // Indexing is crucial for performance! }, { timestamps: true }); // Check if model exists before compiling (Next.js Hot Reload Fix) export const Task = mongoose.models.Task || mongoose.model('Task', TaskSchema);

Common Pitfalls

  • Mistake 1: Over-fetching.
    • Don't: Embed massive arrays.
    • Do: Use pagination for related data (lookup or separate queries).

Pro Tips

  1. Indexes: Always index fields you query by (like projectId in Tasks). It's the difference between 10ms and 10s queries.
  2. Lean Queries: Use .lean() in Mongoose when you just need JSON data and not the heavy document methods.

Wrapping Up

Modeling data in MongoDB requires thinking about how you will read the data. Design for your most frequent queries.

Tech Stack: MongoDB, Mongoose, Next.js