Stackbook Logo
architecture-descriptionestablished · low operational burden

Layered Architecture

Also known as: n-tier-architecture, three-tier-architecture

Intent

Organize code into horizontal layers with distinct responsibilities where each layer depends only on the one below.

Problem

Without structure, presentation, business, and data access code mix together, so changes in one concern force edits everywhere and nothing can be tested in isolation.

Forces

  • •Separation of concerns improves comprehension
  • •Teams need a simple, familiar structure
  • •Strict layering can force pass-through code
  • •Business logic tends to leak into upper or lower layers

Solution

Overview

Layered architecture is the default shape of many enterprise applications. Each layer has a role, and the dependency direction is top to bottom. It is easy to learn and works well until the domain grows richer or features need to evolve independently.

How it works

A request enters the presentation layer, moves through the service layer, uses domain rules, and reaches the data layer.

Presentation   controllers, views
     |
Application    services, transactions
     |
Domain         entities, rules
     |
Data access    repositories, ORM
class OrderController { OrderService svc; }
class OrderService   { OrderRepository repo; }
class OrderRepository { /* SQL */ }

A closed layer must be traversed; an open layer can be skipped. Marking a shared utility layer as open avoids useless delegation. Architecture tests can assert that no class in the data layer imports from presentation.

Pitfalls

  • Sinkhole requests where layers merely forward calls; if most requests behave this way, the layering is not helping.
  • Letting the domain layer depend on persistence, which couples rules to the ORM. Inverting this dependency leads toward hexagonal or clean architecture.
  • Horizontal teams per layer, producing handoffs for every feature.
  • Entities that are bags of getters while all logic lives in services.
  • Stopping at layers when the codebase needs feature-based modules.

Key takeaways

  • Layers separate concerns but spread each feature across many files.
  • Enforce dependency direction automatically.
  • Consider inverting domain-to-data dependency as complexity grows.
  • Move to modules or vertical slices when changes keep crossing every layer.

✓ When to Use

  • •Typical business applications with moderate complexity
  • •Teams new to architecture needing a shared convention
  • •Systems where technical specialization maps to layers

✗ When Not to Use

  • •Highly cohesive features that cut across all layers
  • •Systems needing independent deployment per capability
  • •Domains where logic is rich and data-layer dependence harms the model

Pros

  • +Simple and widely understood
  • +Clear place for each concern
  • +Layers can be tested separately with mocks

Cons

  • −Pass-through layers add boilerplate
  • −Features scatter across layers, so one change touches many
  • −Domain layer often depends on data layer, hurting testability

Cost Profile

Infrastructure

None — code structure

Operational

Low — single deployment typically

Cognitive

Low — familiar structure

Failure Modes

  • Sinkhole anti-pattern where requests pass through layers doing nothing

  • Business logic leaking into controllers or SQL

  • Big ball of mud when layering rules are not enforced

Real-World Examples

Alternatives

    Related Patterns

      Competency Domains

      requirements constraintseconomics evolution