When we build a web application, we usually need a place to store data. This data can be users, blog posts, images or comments. For this we use a database.
In many Next.js projects, developers use MongoDB as the database and Mongoose as the tool to connect with it.
In this blog we will learn how to create a database connection in Next.js using a simple example.
🍃 What is MongoDB
MongoDB is a NoSQL database. It stores data in a flexible format called documents.
These documents look very similar to JavaScript objects, which makes it easy to work with JavaScript frameworks like Next.js.
✨ Example
{
name: "Himanay",
role: "Frontend Developer",
country: "Sweden"
}
Because the structure looks like a JavaScript object, developers can easily read, update and manage data.
🧠 What is Mongoose
Mongoose is a library that helps Node.js connect with MongoDB. It also helps manage database data easily.
👉 Mongoose helps us to
- Connect to the database
- Create models
- Read data
- Write data
- Update and delete data
📦 Install Mongoose
Run this command in your project
npm install mongoose
📁 Step 1 Create Database Connection File
In a Next.js project, we usually create a file called db.ts.
This file handles the database connection so it can be reused in different parts of the application.
📌 Example db.ts
import mongoose from "mongoose";
const MONGODB_URI = process.env.MONGODB_URI!;
if (!MONGODB_URI) {
throw new Error("Please define mongodb uri in env file");
}
let cached = global.mongoose;
if(!cached){
cached = global.mongoose = {conn: null, promise: null};
}
export async function connectToDatabase(){
if(cached.conn){
return cached.conn;
}
if (!cached.promise) {
const opts = {
bufferCommands: true,
maxPoolSize: 10,
};
cached.promise = mongoose
.connect(MONGODB_URI, opts)
.then(() => mongoose.connection);
}
try {
cached.conn = await cached.promise;
} catch (error) {
cached.promise = null;
throw error;
}
return cached.conn;
}
📋 Understanding the Code Step by Step
1️⃣ Import Mongoose
First we import mongoose so we can connect to MongoDB.
import mongoose from "mongoose";
2️⃣ Read the MongoDB Connection URL
Next we read the MongoDB URI from environment variables.
const MONGODB_URI = process.env.MONGODB_URI!;
📄 Example .env.local
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/blogdb
✔ This keeps database credentials secure.
3️⃣ Check if the URI exists
If the MongoDB URI is missing the application will throw an error.
if (!MONGODB_URI) {
throw new Error("Please define mongodb uri in env file");
}
This prevents the app from running with a missing database configuration.
4️⃣ Create a Cached Connection
Next we create a cached connection.
This is important because Next.js reloads the server many times during development.
let cached = global.mongoose;
If the connection does not exist we initialize it.
if(!cached){
cached = global.mongoose = {conn: null, promise: null};
}
📦 This object stores
- conn → active database connection
- promise → pending database connection
This helps reuse the connection instead of creating new ones repeatedly.
5️⃣ Create the Database Connection
Now we create the actual connection.
cached.promise = mongoose
.connect(MONGODB_URI, opts)
.then(() => mongoose.connection);
⚙️ Options used
-
bufferCommands: true
- queues commands before the connection is ready
-
maxPoolSize: 10
- limits the number of database connections
6️⃣ Save the Connection
Once the connection is ready we store it.
cached.conn = await cached.promise;
Now the application will reuse the same connection instead of creating a new one.
7️⃣ Return the Database Connection
Finally the function returns the connection.
return cached.conn;
This allows other parts of the application to use the database.
🧩 TypeScript Global Types File
Next we create a file called types.d.ts.
This helps TypeScript understand the global mongoose variable.
Example
import { Connection } from "mongoose"
declare global {
var mongoose: {
conn: Connection | null
promise: Promise<Connection> | null
}
}
export {};
✔ This prevents TypeScript errors and defines the structure of the cached object.
🔌 How to Use the Connection
Now we can use the connection anywhere in the project.
Example in an API route
import { connectToDatabase } from "@/lib/db";
export async function GET() {
await connectToDatabase();
return Response.json({
message: "Database connected successfully"
});
}
When the API runs
- Connect to MongoDB
- Reuse existing connection if available
- Return the API response
📝 Example in a Blog Project
Imagine we are building a blog platform.
A blog document in MongoDB may look like this
{
title: "Learning Next.js",
content: "Database connection in Nextjs blog",
author: "Himanay"
}
Using the database connection, we can
- ✔ Save blog posts
- ✔ Fetch blog posts
- ✔ Update blog posts
- ✔ Delete blog posts
⚡ Why Connection Caching is Important
❌ Without caching
- Many database connections open
- Database becomes slow
- Server may crash
✅ With caching
- One connection reused
- Faster API requests
- Better performance
📚 Summary
In this blog we learned
- What MongoDB is
- What Mongoose does
- How to create a database connection in Next.js
- Why caching connections is important
- How TypeScript global types help
This setup is commonly used in modern Next.js full stack projects.
The database can store
- 👤 Users
- 📝 Blog posts
- 🖼 Image metadata
🚀 Final Thought
Learning how to create a database connection is one of the first steps in building a full stack Next.js application.
Once the connection works correctly you can start building authentication, blog systems, dashboards and APIs.
Keep learning and keep building projects 💻
Top comments (0)