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)