Layered Architecture
Layered Architecture
Layered architecture organizes a system by technical capability rather than business function. The classic example has four layers: presentation (UI), business logic, persistence (data access), and database. Each layer depends only on the layer directly below it, creating a clean separation of technical concerns.
How It Works
The presentation layer handles user interaction and delegates business operations to the business layer. The business layer implements domain logic and uses the persistence layer to read and write data. The persistence layer abstracts database access. The database stores the data.
Layers can be “closed” (forcing requests through every layer) or “open” (allowing layers to be skipped). Closed layers provide better isolation; changes to one layer don’t ripple through others. Open layers improve performance by avoiding unnecessary pass-through calls.
Closed vs Open Layers
Closed layers force requests to flow through every layer in sequence. The presentation layer must call the business layer, which must call the persistence layer, which accesses the database. No skipping allowed.
This strict flow provides isolation. If the persistence layer changes how it accesses the database, the business layer doesn’t care; it only knows the persistence layer’s interface. Changes are contained within layers.
Open layers allow components to skip layers when appropriate. For example, if the presentation layer needs to read static reference data that requires no business logic, it might call the persistence layer directly, bypassing the business layer.
Open layers improve performance by eliminating unnecessary pass-through calls. But they create dependencies that cross layers, making changes riskier. Use open layers sparingly and only when the performance benefit justifies the coupling cost.
The Sinkhole Antipattern
The sinkhole antipattern happens when too many requests pass straight through layers without any processing. If 80% of your requests flow from presentation to persistence without significant business logic, you’re paying the cost of layers without getting their benefits.
This suggests one of two problems:
Wrong layer boundaries: Maybe you’re organizing by the wrong technical concerns. The system’s natural structure doesn’t align with the layering model.
Primarily CRUD operations: If the system is mostly create, read, update, delete operations with minimal business logic, layered architecture adds ceremony without value. Consider a simpler architecture that embraces the CRUD nature rather than fighting it.
The 80/20 rule applies here. If 20% or fewer of your requests pass through without logic, that’s acceptable. If more than 80% are pass-throughs, you have a sinkhole problem.
Topology Details
Presentation Layer
- Handles user interaction (web UI, mobile app, API endpoints)
- Manages display logic and user input validation
- Delegates business operations to the business layer
- Does NOT contain business logic
- Does NOT access the database directly
Business Layer
- Implements domain logic and business rules
- Coordinates workflow across domain concepts
- Enforces business constraints and validation
- Uses the persistence layer for data access
- Does NOT know about UI concerns
- Does NOT contain SQL or data access code
Persistence Layer
- Abstracts database access behind interfaces
- Translates between domain objects and database schemas
- Handles SQL queries, ORM mapping, and connection management
- Provides data access methods used by the business layer
- Does NOT contain business logic
- Does NOT know about UI concerns
Database Layer
- Stores data persistently
- Enforces data integrity constraints
- Provides transactional guarantees
- May contain stored procedures (though this creates coupling)
Characteristics
| Characteristic | Rating | Notes |
|---|---|---|
| Simplicity | ⭐⭐⭐⭐⭐ | Easy to understand and explain |
| Scalability | ⭐ | All layers scale together; no independent scaling |
| Evolvability | ⭐⭐ | Changes often affect multiple layers |
| Deployability | ⭐⭐⭐ | Single deployment unit is simple |
| Testability | ⭐⭐⭐ | Layers can be mocked for testing |
| Modularity | ⭐⭐ | Technical partitioning doesn’t match domain concepts |
| Cost | ⭐⭐⭐⭐⭐ | Low cost; requires minimal infrastructure |
When Layered Architecture Fits
Small applications with straightforward business logic: When the system is simple enough that organizing by technical concerns makes sense and the overhead of layers doesn’t outweigh their benefits.
Tight budgets requiring fast initial development: Layered architecture is conceptually simple and doesn’t require sophisticated infrastructure. Teams can build and deploy quickly without learning distributed system patterns.
Starting point when requirements are unclear: When you don’t yet know what the system needs to do, layered architecture provides a familiar structure while you discover requirements. You can refactor to a different style later if needed.
MVPs and prototypes: For systems where speed to market matters more than long-term scalability or evolvability. Get something working quickly, learn from users, then decide whether to refactor or rebuild.
Teams new to the domain: When the team doesn’t understand the business domain well enough to partition by domain concepts, technical layers provide a safe starting structure.
When to Avoid Layered Architecture
Large applications where scalability matters: You can’t scale the presentation layer separately from business logic. Everything scales together, wasting resources and limiting maximum scale.
Systems where evolvability matters: Changes to domain concepts often ripple across all layers. Adding a new field means touching presentation, business, persistence, and database layers. This makes change expensive and risky.
Independent deployment requirements: The entire system deploys as one unit. You can’t deploy a change to the presentation layer without deploying the entire application. This limits deployment frequency and increases risk.
Different operational characteristics needed: If some parts of the system need high availability while others don’t, or some parts need different scaling characteristics, layered architecture can’t accommodate these differences. Everything shares the same operational profile.
As the codebase grows: Navigation and maintenance become increasingly difficult. Finding where logic lives becomes harder. Understanding dependencies across layers requires holding more context in your head.
Common Pitfalls
Business logic leaking into presentation layer: UI code contains business rules because it’s “convenient.” This creates duplication (mobile and web both implement the same rules) and makes business logic hard to test.
Persistence logic leaking into business layer: Business logic contains SQL queries or ORM-specific code. This couples business rules to database structure and makes testing harder.
Too many layers: Adding layers for “flexibility” without clear purpose. Each layer adds indirection and complexity. Only add layers when they provide clear benefits.
Inconsistent layer boundaries: Some components follow layering strictly while others shortcut. This creates confusion about the architecture’s actual rules and makes the codebase harder to navigate.
Anemic domain model: Business layer objects become pure data containers with no behavior. All logic moves to service classes. This is often a sign that domain-driven design or a different architectural style would fit better.
Evolution and Alternatives
When layered architecture stops working:
Evolve to modular monolith: Reorganize by business domains instead of technical layers. Each module contains its own presentation, business, and persistence logic. This improves modularity while maintaining monolithic deployment.
Evolve to service-based architecture: Extract coarse-grained services for major business capabilities. This enables independent scaling and deployment while avoiding microservices complexity.
Stick with layering but improve modularity: Use Domain-Driven Design tactical patterns within the business layer to better organize domain logic. This doesn’t change the architectural style but can improve maintainability.
For more architectural style options, see the Architecture Styles overview.
Found this guide helpful? Share it with your team:
Share on LinkedIn