Skip to content

Layered (n-tier) architecture

A layered architecture organizes an application into horizontal layers, each with one kind of responsibility. A request enters at the top (the user interface or API), passes down through business logic, and reaches the data layer at the bottom. Each layer depends only on the layer beneath it.

It is the most widely taught style and the default shape of many enterprise applications, because it separates concerns in a way most developers recognize immediately.

flowchart TB
    ui["Presentation layer<br/>UI, controllers, API endpoints"]
    biz["Business layer<br/>rules, workflows, validation"]
    data["Data access layer<br/>repositories, queries"]
    db[(Database)]
    ui --> biz --> data --> db
  • Separation by technical concern. Presentation, business logic and persistence each live in their own layer.
  • Downward dependencies only. A layer calls the layer below it, never above.
  • Closed or open layers. In a closed layer, requests must pass through it. An open layer can be skipped, which is convenient but weakens the separation.
  • Usually one deployment. All layers are typically deployed together, although tiers can also run on separate servers (hence “n-tier”).
  • Familiar: almost every developer understands it, so onboarding is quick.
  • Clear separation of concerns: UI changes rarely touch the database code.
  • Easy to start: most frameworks scaffold this structure by default.
  • Testable layers: each layer can be tested with the one below replaced by a stub.
  • Changes cut across every layer: adding one field often means editing the UI, the business layer and the data layer.
  • Business logic leaks: without discipline, rules drift into controllers or SQL.
  • Organized by technology, not business: code for one feature is scattered across layers, which makes large codebases hard to navigate.
  • Pass-through layers: layers that only forward calls add code without adding value.
  • Small and medium applications with straightforward business logic.
  • Teams new to architecture who need a clear, conventional structure.
  • Internal line-of-business applications built mainly around data entry and reporting.
  • Complex domains where business rules deserve isolation from frameworks and databases. Consider hexagonal architecture.
  • Large systems worked on by many teams, where organizing by feature or module scales better. Consider a modular monolith.
  • The anemic domain model. Entities become plain data holders, and all logic piles up in large “service” classes.
  • The architecture sinkhole. Most requests pass straight through every layer with no processing. If this describes most of your code, the layers aren’t earning their keep.
  • Leaky persistence. Database entities or query objects returned all the way up to the UI couple the top layer to the bottom one.

Glossary: coupling

  • Mark Richards, Software Architecture Patterns (O’Reilly report)
  • Martin Fowler, Patterns of Enterprise Application Architecture

Written and edited by Abhinav Taduka, enterprise software architect.