REST and MVC: Complementary, Not Competing
A common misconception is that REST and MVC are competing patterns. They are not — they operate at different layers. REST defines how clients talk to your server (the API interface). MVC defines how your server is organized internally (the code structure).
REST is the Interface, MVC is the Organization:
Client REST API MVC Backend Database
+----------+ +--------------+ +------------------+ +-----------+
| | | | | | | |
| Browser | HTTP | /api/users | | Controller | | |
| Mobile | ---------> | /api/items | --------> | | | | PostgreSQL|
| Another | | /api/orders | | v | | MongoDB |
| Service | <--------- | | <-------- | Model --> View | <--> | MySQL |
| | JSON/HTML | Defines: | | | | |
+----------+ | - URLs | | Organizes: | +-----------+
| - Methods | | - Data logic |
| - Status | | - Presentation |
| codes | | - Flow control |
+--------------+ +------------------+
Think of it this way:
- REST is like the menu at a restaurant — it defines what you can order and how to ask for it
- MVC is the kitchen organization — how the chefs, prep cooks, and plating stations are arranged to fulfill those orders
You can have REST without MVC (a single-file API script), MVC without REST (a server-rendered app with no API), or both together (which is the most common real-world pattern).
MVC in Popular Frameworks
Every major web framework organizes code using MVC (or something very close to it). The concepts are the same; only the file names and conventions differ:
| Framework | Routes | Controller | Model | View / Template |
|---|---|---|---|---|
| Express (Node.js) | routes/users.js |
controllers/userController.js |
models/User.js |
views/users/index.ejs |
| Laravel (PHP) | routes/web.php |
app/Http/Controllers/UserController.php |
app/Models/User.php |
resources/views/users/index.blade.php |
| Django (Python) | urls.py |
views.py |
models.py |
templates/users/index.html |
| Rails (Ruby) | config/routes.rb |
app/controllers/users_controller.rb |
app/models/user.rb |
app/views/users/index.html.erb |
The Route-Handler-Model Pattern
Regardless of the framework, the flow is always the same: a route maps a URL to a handler (controller), which calls the model for data, then returns a response. Here is the pattern in each major framework:
Express (Node.js)
Laravel (PHP)
Django (Python)
Rails (Ruby)
The file names and syntax differ, but the architecture is identical: Route → Controller → Model → View.
Choosing Your Architecture
With a clear understanding of REST and MVC as separate, complementary layers, here is a summary of how to choose your approach:
| Concept | Key Points |
|---|---|
| MVC | A pattern that separates an application into Model (data), View (presentation), and Controller (logic/flow). Not tied to any framework or language. |
| Model | Manages data and business rules. Knows how to talk to the database. Has no knowledge of how data is displayed. |
| View | Renders output (HTML, JSON, etc.). Takes data from the Model and formats it for the client. Has no knowledge of data storage. |
| Controller | Receives user input, coordinates the Model and View. The "traffic cop" that routes requests to the right code. |
| Server-Side MVC | Server renders complete HTML pages. Browser just displays them. Best for content sites, SEO, and progressive enhancement. Frameworks: Express+EJS, Laravel, Django, Rails. |
| Client-Side MVC | Server sends JSON, client JavaScript renders the UI. Best for highly interactive apps. Frameworks: React, Vue, Angular. Requires JS to function. |
| Adaptable MVC | Same controller serves HTML or JSON based on the Accept header. Progressive enhancement: works without JS, enhanced with it. |
| REST vs MVC | REST defines the external API interface (URLs, methods, status codes). MVC organizes internal server code. They are complementary, not competing. |
| ORMs | Object-Relational Mappers let Models interact with the database using objects instead of raw SQL. Examples: Sequelize (Node.js), Eloquent (Laravel), Django ORM, ActiveRecord (Rails). |