Building a Next.js 14 App with MongoDB: The Complete 2025 Guide
Complete guide to building production Next.js 14 apps with MongoDB using App Router and server components.
From zero to production — a step-by-step walkthrough of building a full-stack Next.js 14 application with MongoDB, covering App Router, server components, and modern data patterns.
Building a Next.js 14 App with MongoDB: The Complete 2025 Guide
Next.js 14 changed everything with the App Router, React Server Components, and a dramatically improved developer experience. Paired with MongoDB, you get a full-stack setup that's both powerful and ergonomic.
Prerequisites
- Node.js 18+
- MongoDB Atlas account (free tier works)
- Basic TypeScript knowledge
Project Setup
npx create-next-app@latest my-app --typescript --tailwind
cd my-app
npm install mongoose
The Database Connection Pattern
The most important pattern in Next.js + Mongoose is connection caching:
import mongoose from 'mongoose';
const cached = global._mongoCache || { conn: null, promise: null };
export default async function connectDB() {
if (cached.conn) return cached.conn;
if (!cached.promise) {
cached.promise = mongoose.connect(process.env.MONGODB_URI!);
}
cached.conn = await cached.promise;
return cached.conn;
}
Without this, you'll create a new connection on every hot reload in development — and hit connection limits fast in production.
Server Components + MongoDB
The beauty of App Router is fetching directly in server components:
// app/posts/page.tsx
import connectDB from '@/lib/db';
import Post from '@/models/Post';
export default async function PostsPage() {
await connectDB();
const posts = await Post.find({ status: 'published' }).lean();
return (
<div>
{posts.map(post => (
<article key={post._id.toString()}>{post.title}</article>
))}
</div>
);
}
No useEffect, no loading states, no API calls. Just data.
API Routes for Mutations
For create/update/delete, use Route Handlers:
// app/api/posts/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
await connectDB();
const body = await req.json();
const post = await Post.create(body);
return NextResponse.json({ post }, { status: 201 });
}
Indexing for Performance
Always add indexes to fields you query frequently:
PostSchema.index({ slug: 1 });
PostSchema.index({ status: 1, publishedAt: -1 });
PostSchema.index({ title: 'text', content: 'text' }); // Full-text search
Conclusion
Next.js 14 + MongoDB is one of the most productive full-stack combinations available today. The App Router makes server-side data fetching feel natural, and Mongoose keeps your data layer clean and typed.
Share this post