docs/nextjs.md
Next.js is a popular framework for building full stack applications with React. Mongoose works out of the box with Next.js. If you're looking to get started, please use Next.js' official Mongoose sample app. Furthermore, if you are using Next.js with Vercel Serverless Functions, please review Mongoose's AWS Lambda docs.
Here's a basic example of using Mongoose with Next.js App Router:
// lib/mongodb.js
import mongoose from 'mongoose';
const MONGODB_URI = process.env.MONGODB_URI;
export default dbConnect;
async function dbConnect() {
if (!MONGODB_URI) {
throw new Error('Please define the MONGODB_URI environment variable');
}
await mongoose.connect(MONGODB_URI);
return mongoose;
}
Then use it in your API routes or Server Components:
// app/api/users/route.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export async function GET() {
await dbConnect();
const users = await User.find({});
return Response.json({ users });
}
Mongoose handles connection management automatically. Calling mongoose.connect() when Mongoose is already connected is a no-op, so you can safely call dbConnect() in every API route and Server Component without worrying about creating multiple connections.
Store your MongoDB connection string in .env.local:
MONGODB_URI=mongodb://localhost:27017/mydb
For production, use environment variables in your hosting platform (Vercel, Netlify, etc.).
Define your models in a separate directory and ensure they're only registered once:
// models/User.js
import mongoose from 'mongoose';
const UserSchema = new mongoose.Schema({
name: String,
email: { type: String, required: true }
}, { timestamps: true });
export default mongoose.models.User || mongoose.model('User', UserSchema);
The mongoose.models.User || mongoose.model('User', UserSchema) pattern prevents model recompilation errors during hot reloading in development.
There are a few common issues when working with Next.js that you should be aware of.
You can fix this issue by adding the following to your next.config.js:
const nextConfig = {
experimental: {
esmExternals: "loose", // <-- add this
serverComponentsExternalPackages: ["mongoose"] // <-- and this
},
// and the following to enable top-level await support for Webpack
webpack: (config) => {
config.experiments = {
topLevelAwait: true
};
return config;
},
}
This issue is caused by this change in MongoDB's bson parser. MongoDB's bson parser uses top-level await and dynamic import in ESM mode to avoid some Webpack bundling issues. And Next.js forces ESM mode.
If you're using Next.js Pages Router, you can use Mongoose in API routes and getServerSideProps:
// pages/api/users.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export default async function handler(req, res) {
await dbConnect();
if (req.method === 'GET') {
const users = await User.find({});
return res.status(200).json({ users });
}
if (req.method === 'POST') {
const user = await User.create(req.body);
return res.status(201).json({ user });
}
res.status(405).json({ error: 'Method not allowed' });
}
Using in getServerSideProps:
// pages/users.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export async function getServerSideProps() {
await dbConnect();
const users = await User.find({});
return {
props: {
users: JSON.parse(JSON.stringify(users))
}
};
}
export default function UsersPage({ users }) {
return (
<div>
<h1>Users</h1>
{users.map(user => (
<div key={user._id.toString()}>{user.name}</div>
))}
</div>
);
}
Important: Use JSON.parse(JSON.stringify()) to convert Mongoose documents to plain objects, as Next.js requires serializable data.
With Next.js 13+ App Router, you can use Mongoose directly in Server Components:
// app/users/page.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export const runtime = 'nodejs';
export default async function UsersPage() {
await dbConnect();
const users = await User.find({}).lean();
return (
<div>
<h1>Users</h1>
{users.map(user => (
<div key={user._id.toString()}>{user.name}</div>
))}
</div>
);
}
Mongoose does not currently support Next.js Edge Runtime.
There is no way for Mongoose to connect to MongoDB in Edge Runtime, because Edge Runtime currently doesn't support Node.js net API, which is what the MongoDB Node Driver uses to connect to MongoDB.