DEV Community

Shahin Idrisi
Shahin Idrisi

Posted on

πŸ” Understanding Model, Controller, and Route in MERN Stack with Example

When building a full-stack application using the MERN stack (MongoDB, Express, React, Node.js), the backend architecture plays a critical role in ensuring the application is well-structured, scalable, and easy to maintain.

In this blog post, we’ll explore the relationship between Model, Controller, and Route in a MERN backend setup and walk through a dummy example to help you understand how they communicate with one another.

πŸ“¦ What is the MVC Pattern?
The MERN backend usually follows the MVC pattern:

Model – Interacts with the database (MongoDB)

Controller – Contains logic to handle requests/responses

Route – Defines the API endpoints

View – In MERN, this is handled by React on the frontend

🧠** Flow of Communication**
Here's how everything connects:

Client sends a request to an API endpoint (like /api/students/add)

Route catches the request and passes it to the correct Controller

Controller uses a Model to interact with MongoDB

Model returns data to Controller, which sends a response back to Client

πŸ“˜ Dummy Example: Student Management API
Let’s create a basic API to manage student records.

Folder Structure:
backend/
β”œβ”€β”€ controllers/
β”‚ └── studentController.js
β”œβ”€β”€ models/
β”‚ └── studentModel.js
β”œβ”€β”€ routes/
β”‚ └── studentRoutes.js
β”œβ”€β”€ server.js

1️⃣ Model – models/studentModel.js

const mongoose = require('mongoose'); const studentSchema = new mongoose.Schema({ name: { type: String, required: true }, rollNumber: { type: Number, required: true }, class: { type: String, required: true }, }); const Student = mongoose.model('Student', studentSchema); module.exports = Student; 
Enter fullscreen mode Exit fullscreen mode

What it does: Defines a Mongoose schema to store student info in MongoDB.

2️⃣ Controller – controllers/studentController.js

const Student = require('../models/studentModel'); // Get all students const getAllStudents = async (req, res) => { try { const students = await Student.find(); res.status(200).json(students); } catch (error) { res.status(500).json({ message: 'Error fetching students' }); } }; // Add a new student const addStudent = async (req, res) => { const { name, rollNumber, class: studentClass } = req.body; try { const newStudent = new Student({ name, rollNumber, class: studentClass }); await newStudent.save(); res.status(201).json(newStudent); } catch (error) { res.status(400).json({ message: 'Failed to add student' }); } }; module.exports = { getAllStudents, addStudent }; 
Enter fullscreen mode Exit fullscreen mode

What it does: Contains the logic to get students from DB or add a new one.

3️⃣ Routes – routes/studentRoutes.js

 const express = require('express'); const router = express.Router(); const { getAllStudents, addStudent } = require('../controllers/studentController'); router.get('/', getAllStudents); // GET /api/students/ router.post('/add', addStudent); // POST /api/students/add module.exports = router; 
Enter fullscreen mode Exit fullscreen mode

What it does: Maps API endpoints to controller functions.

4️⃣ Server Entry – server.js

 const express = require('express'); const mongoose = require('mongoose'); const studentRoutes = require('./routes/studentRoutes'); const app = express(); // Middleware app.use(express.json()); // Routes app.use('/api/students', studentRoutes); // Connect MongoDB and start server mongoose.connect('mongodb://127.0.0.1:27017/school') .then(() => { console.log('MongoDB Connected'); app.listen(5000, () => console.log('Server running on port 5000')); }) .catch((err) => console.log(err)); 
Enter fullscreen mode Exit fullscreen mode

_What it does: Connects all parts and starts the Express server.
_

πŸ”„ How a Request Flows
When a POST request is sent to /api/students/add:

Route in studentRoutes.js catches it

It calls addStudent() from studentController.js

The controller creates a new Student using the Model

The Model saves it to MongoDB

A JSON response is sent back to the client

🧩 Final Thoughts
Understanding the communication between Model, Controller, and Route is key to mastering backend development in MERN. Once you get this flow, your projects become much easier to scale and maintain.

πŸ”§ Want to connect this backend to a React frontend? Let me know in the comments and I’ll write a follow-up!

✍️ Author: Shahin Idrisi
πŸ’¬ Feel free to reach out for help with your MERN projects!

Top comments (1)

Collapse
 
rushabhcodes profile image
Rushabh Patil

πŸ”₯πŸ”₯πŸ”₯