vishal patel
Applied in productionFoundationUpdated 2026-09-23

Layered (N-Tier) Architecture

Split an application into horizontal layers — presentation, application, domain, data — where each layer only calls the one below it.

structuremonolithseparation-of-concerns

The problem

Without structure, UI code talks to SQL, business rules hide in controllers, and a change to the database ripples through every screen. Layering is the oldest answer: group code by technical responsibility and control the direction of dependencies.

How it works

diagram
  • Closed layers: a request must pass through each layer in turn. This keeps the isolation.
  • Open layers: some layers can be skipped, such as a shared utilities layer. Use them sparingly, or the isolation disappears.
  • Each layer exposes an interface to the layer above it and hides its internals.
Use it when
  • Small-to-medium apps and CRUD-heavy line-of-business systems
  • Teams that are new to the domain and need a familiar structure
  • You need to ship fast and the domain logic is thin
Avoid it when
  • Domain logic is rich and must be tested without the DB
  • Many teams need to deploy independently
  • You notice the 'sinkhole' anti-pattern: most requests just pass straight through every layer

Trade-offs

  • ✅ Simple, well understood, easy to onboard people.
  • ✅ Clear place for each kind of code.
  • ❌ The domain layer usually ends up depending on the data layer, so business rules get coupled to persistence. Hexagonal and Clean architecture fix this by inverting that dependency.
  • ❌ It's a technical partitioning. A single feature change touches every layer, which makes team ownership awkward.
Where I've used it

My early .NET systems (the time-tracking system at DNEG, line-of-business apps at Prime Focus) were classic 3-tier: ASP.NET → service layer → SQL Server. They were quick to build, but once rules grew, the stored procedures started holding business logic. That's the moment to move toward a domain-centric style.

In one line

Layered architecture partitions code by technical concern and enforces top-down dependencies. It's the right default for simple apps, but I invert the domain → data dependency once business rules matter.

Sources & further learning

Videos, courses, docs and books I recommend for this topic.

Related topics