
It made sense at the time.
So did 3-tier applications and monoliths.
Controller → Service → Repository.
It’s everywhere. It’s predictable. And every bootcamp teaches it.
But that doesn’t mean it’s always the right choice.
Let’s talk about when layering helps… and when it just gets in the way.
The Case for Layers
Layers exist for a reason: separation of concerns.
- Controllers handle inputs and outputs (HTTP, CLI, etc.)
- Services hold business logic
- Repositories deal with data storage
This structure keeps things clean. Each part has a job.
On paper, it makes code easier to test and safer to change.
Where It Falls Apart
In real-world systems, the layer cake starts to crumble.
You Write Layers That Just Pass Data
// controller
export const getUser = (req, res) => {
const user = userService.getUserById(req.params.id)
res.send(user)
}
// service
const getUserById = (id) => {
return userRepository.getById(id)
}
// repository
const getById = (id) => {
return db.users.find((user) => user.id === id)
}Three files. No real logic. Just pass-throughs.
One Change Touches Three Files
Need to add a field or flag?
You’re now editing controller, service, and repository just to wire it through.
Tests Become Glue Validation
You’re not testing actual behavior.
You’re testing that functions delegate correctly.
What Can We do
Don’t follow a pattern just because it looks clean.
Instead:
- Collapse layers when there’s no meaningful logic to separate
- Group code by feature, not by type
- Use vertical slices to keep related code close together
- Let real behavior and complexity guide your structure
Vertical Slice vs Layered
Layered architecture stacks everything by role:
UI → Logic → Database
Vertical slices cut by feature:
Auth, Orders, Notifications
Each slice contains only what it needs that is input handling, logic, and data.
It reduces file-hopping and helps the code evolve more naturally.
When Layers Still Make Sense
Layered architecture can still work well when:
- You have meaningful business logic separated from data access
- The application is stable and layering prevents coupling
- You’re on a large team with strict role boundaries
But if you're on a small team, building fast, or mostly doing CRUD?
Favor clarity. Not ceremony.
The Takeaway
Layered architecture is a tool, not a rule.
Sometimes, one well-named function is better than splitting logic across three files “because architecture.”
The goal is working software. Not perfect structure.
You Can Check Them Out Too
some cool interesting stuff