Why you can't just call mongoose.connect() directly
Next.js reloads modules constantly while you're developing. If you don't cache the connection somewhere, every single reload opens a brand-new connection to MongoDB, and before long you've blown through the pool limit. The pattern below is the fix everyone eventually lands on.
Step 1 – Install Mongoose
npm install mongoose
Step 2 – The connection helper
Create src/lib/db.ts and stash the connection promise on Node's global object so it survives hot reloads instead of being recreated each time.
import mongoose from "mongoose";
declare global {
// eslint-disable-next-line no-var
var _mongooseConn: Promise<typeof mongoose> | undefined;
}
export async function connectDB() {
if (!global._mongooseConn) {
global._mongooseConn = mongoose.connect(process.env.MONGODB_URI!, {
bufferCommands: false,
});
}
return global._mongooseConn;
}
Step 3 – Your first model
Use the models.X || model("X", schema) guard - skip it and you'll eventually hit the classic "Cannot overwrite model once compiled" error during a hot reload.
import mongoose, { Schema, models, model } from "mongoose";
const PostSchema = new Schema(
{
title: { type: String, required: true },
content: { type: String, required: true },
slug: { type: String, required: true, unique: true },
},
{ timestamps: true }
);
const Post = models.Post || model("Post", PostSchema);
export default Post;
Step 4 – Querying from a Server Component
Just call connectDB() at the top of any Server Component or Route Handler before you touch the database - that's really all there is to it.
import { connectDB } from "@/lib/db";
import Post from "@/models/Post";
export default async function BlogPage() {
await connectDB();
const posts = await Post.find({}).lean();
return <ul>{posts.map(p => <li key={p._id.toString()}>{p.title}</li>)}</ul>;
}Comments
Loading comments...
Related Articles
Taming Slow MongoDB Aggregation Pipelines in Production
An aggregation pipeline that returns instantly on your 500-document local dataset can crawl once it hits a few million real documents. Here's how to actually find and fix the stage that's costing you.
Read ArticleBuilding a Sliding-Window Rate Limiter for Node.js APIs with Redis
Fixed-window rate limiting looks fine in a demo and then lets through double the traffic right at the window boundary. Here's the sliding-window-counter approach that fixes that, built directly on Redis.
Read ArticleMulti-Tenant Data Isolation: Shared Schema vs Separate Databases
Every multi-tenant SaaS eventually has to answer one question honestly: how do you stop one customer from ever seeing another customer's data? Here's how the three common isolation strategies actually compare in practice.
Read Article