LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 3718 min read

Connecting a Node.js App to MongoDB

Wire up a complete Express + Mongoose application, from connection setup through a working REST endpoint.

Project Structure

A typical Express + Mongoose project separates concerns into models, routes, and a connection module.

src/
├── models/
│ └── User.js
├── routes/
│ └── users.js
├── db.js
└── server.js

Environment-Based Configuration

The database connection string should always come from an environment variable, never hardcoded — keeping credentials out of source control and letting the same code point to different databases per environment.

# .env
MONGODB_URI=mongodb+srv://user:pass@cluster0.abcde.mongodb.net/myapp

A Database Connection Module

// db.js
import mongoose from 'mongoose';
export async function connectDB() {
await mongoose.connect(process.env.MONGODB_URI);
console.log('MongoDB connected');
}
// models/User.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
});
export const User = mongoose.model('User', userSchema);

A Complete REST Endpoint

// routes/users.js
import express from 'express';
import { User } from '../models/User.js';
const router = express.Router();
router.post('/users', async (req, res) => {
try {
const user = await User.create(req.body);
res.status(201).json(user);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
router.get('/users', async (req, res) => {
const users = await User.find();
res.json(users);
});
export default router;
// server.js
import express from 'express';
import { connectDB } from './db.js';
import usersRouter from './routes/users.js';
await connectDB();
const app = express();
app.use(express.json());
app.use('/api', usersRouter);
app.listen(3000, () => console.log('Server running on port 3000'));

Common Beginner Mistakes

Starting the server before the database connection resolves

Calling app.listen() before connectDB() completes can let requests through before Mongoose is ready — await the connection first, as shown above.

Not handling Mongoose errors in route handlers

A validation or duplicate-key error from create() should be caught and turned into a proper 400/409 response, not left to crash the request unhandled.

FAQs

Yes — this is the standard pattern; each route/controller imports the specific models it needs from a shared models/ folder.

Mongoose's underlying driver automatically attempts to reconnect; a request in flight during a drop will typically error, which your route's error handling should catch and respond to appropriately.

Summary

A well-structured Express + Mongoose app separates models, routes, and connection setup, with configuration driven by environment variables. With application integration covered, the next section moves into advanced, production-focused MongoDB topics — starting with transactions.

Next Lesson →

Transactions in MongoDB