Layered Architecture
Concept
A structure that stacks the inside of one program into presentation, business, and data layers, where each layer only calls the one below it.
Why it exists
When code isn't split into layers, commands sent to the database — the system that stores data and hands it back — end up sitting in the middle of the code that draws the screen. Scatter those commands across twenty screen files and the consequences show up fast.
The file that renders the order list contains a query. The admin screen contains a similar one. The code that sends email contains a third. Change the discount rule and all three have to be found and edited, and missing one means the admin screen quietly keeps showing the old number. Customers find that bug before the team does.
Verification breaks for the same reason. Checking whether a discount calculates correctly means loading the page, logging in, and adding an item to a cart. There's nowhere to attach a unit test, which checks a single function in isolation, because the rule is welded to screen code and can't be pulled out.
Layered architecture is the answer that separates those jobs by kind. Showing, deciding, and storing each get their own layer, and the direction of calls between layers is fixed one way. It is the oldest approach to organizing software this way, and still the most widely used.
How it works
Stack three layers and allow calls in one direction only. Requests travel down and results come back up. A lower layer never calls an upper one.
- The presentation layer is what users see. It draws screens, takes input, and shows results. It does not decide anything — it doesn't work out the discount rate, it asks the layer below.
- The business layer decides. Business logic, the business rules translated into code, gathers here. Whether a coupon applies to this order, how large the discount is, what happens when stock runs short.
- The data layer stores and retrieves. Every command sent to the database lives here. The layer above just says "fetch order 3" and never learns what that command looks like.
Fixing the direction is the entire idea. Allow lower layers to call upward and the data layer starts holding code that pops a warning on screen, and at that moment the layers are names and nothing else. Nothing in a programming language enforces the rule by itself, so teams hold it with review comments, folder-level import checks, or a build step that fails when the wrong direction appears.
Skipping a layer is blocked for the same reason. If the presentation layer reaches past the business layer straight into the data layer, the discount rule goes missing on that one path. A screen may look like it only reads data, but read results usually carry rules of their own.
Splitting into layers also creates the need to hand values across the boundaries. Passing database table shapes straight up means a table change breaks the screen, so values get copied into dedicated shapes between layers. That copying is the price of the split, and it grows with every extra layer. A field added to an order shows up in three or four files that do nothing but carry it along, which is why teams that hate the boilerplate often relax the rule for simple reads and keep it strict everywhere a rule applies.
Where it shows up
It's the default when server code gets written from scratch. Most web frameworks lay out their folders assuming this arrangement, so teams often land in it without deciding to.
It most often appears alongside a monolith, where everything ships as one deployable unit. The two are decisions at different levels: monolith describes how many pieces exist from the outside, layered describes the arrangement inside a piece. Monolith plus layered is the common case, and each service in a microservices setup — where functions are split and deployed separately — is usually layered inside too.
The structure also works as a map when a new engineer is shown around. Fixing screen wording means opening the presentation layer, and a wrong calculation means the business layer. Not having to ask where to look is the practical benefit, and it compounds: the same map tells a reviewer which file a change should have touched, so a fix landing in the wrong layer stands out on its own.
The arrangement fits badly in one case worth naming. If a program only takes values from a screen and saves them, the business layer does nothing but pass things along, and the cost of three layers arrives without the return. Inserting a layer later, once real rules exist, works fine.
How it sounds at work
"Why is this calculation in the controller? Move it down to the business layer."
Deciding code has crept up into the presentation layer. Leave it and the same calculation gets rewritten for the next screen.
"Let's start layered and split it later if we need to."
A proposal to take the familiar default and postpone the structural argument.
"The layers are there, but the business layer is empty."
Three layers by name, with the actual decisions scattered across the other two.
When Theo first pushed the document sharing feature at Pagedeck, the permission check sat inside the screen code. The review comment wasn't that the behavior was wrong — it was that the same check was about to exist in three places. External share links and the mobile screen needed the identical rule, and reconciling three copies later guarantees one of them drifts.
After the move, the permission rule became one function in the business layer. When the "anyone with the link" condition was added later, one file changed, and the unit tests on that function confirmed the existing conditions still held. Mia, who wrote the requirement, could read that single function to check the rule matched what she had specified.
What people get wrong
Many people assume three folders make an architecture. Structure gets taught through folder names, so the assumption is natural. What actually creates the structure is the constraint on call direction. One line where a presentation file calls a data layer function directly means there are no layers on that path. Let those lines accumulate and you get three folders over a codebase where anything calls anything, which is the worst state of the three. The team believes it is separated while it isn't, so every change breaks something nobody expected.
Believing more layers are better is the other common one. Turning three layers into five adds copy-between-layers code at every new boundary. When adding one field to a screen means editing five files, people start skipping layers instead. Add a layer only when work of a genuinely different kind is mixed in.
Easily confused with
| Term | What sits at the center | How it differs |
|---|---|---|
| Hexagonal architecture | The business rules | Treats the database as a replaceable part rather than the bottom layer. The business layer doesn't depend on the data layer, so changing how things are stored leaves the rules untouched |
Where to go next
- Software architecture
see the full set of criteria for choosing a structure
- Monolith
the deployment-unit decision this one is usually paired with
Last updated 2026-09-16