Layered Architecture
Layered architecture organizes code into horizontal tiers — typically presentation, business logic, persistence — where each layer depends only on the layer directly below.
Introduction
Layered architecture organizes code into horizontal tiers — typically presentation, business logic, persistence — where each layer depends only on the layer directly below. It is the default structure in Spring Boot, Django, and .NET apps and remains the foundation inside individual microservices.
In HLD, layered architecture applies within a service boundary, not across the whole system. Interviewers want to see clean separation: controllers handle HTTP, services enforce rules, repositories access data. Violations (SQL in controllers) signal maintainability risk.
This lesson connects classic n-tier design to modern hexagonal/ports-and-adapters thinking without overcomplicating the interview answer.
Understanding the topic
Key concepts
- Presentation layer: REST controllers, DTO validation, auth context extraction.
- Application/service layer: use cases, transactions, domain rules orchestration.
- Persistence layer: repositories, ORM entities, query optimization.
- Dependency direction: top → down only; domain core should not depend on web framework.
- Cross-cutting: logging, metrics, security filters span layers via aspects or middleware.
- Hexagonal variant: ports (interfaces) and adapters (REST, JPA) swap infrastructure easily.
flowchart TBUI --> ControllerController --> ServiceService --> RepositoryRepository --> DB
Internal architecture
Architecture overview
flowchart TBUI --> ControllerController --> ServiceService --> RepositoryRepository --> DB
Step-by-step explanation
- HTTP request enters Controller → validates DTO → calls Service interface.
- Service opens transaction, applies business logic, calls Repository.
- Repository maps entities to PostgreSQL via JPA/MyBatis.
- Service returns domain result → Controller maps to response DTO (never expose entities).
- Errors bubble as domain exceptions → @ControllerAdvice maps to HTTP status.
- Async side effects delegated to application events or message publisher from service layer.
Informative example
Classic Spring layered stack with DTO mapping separated from JPA entities:
@RestController@RequestMapping("/api/v1/accounts")class AccountController {private final AccountService service;AccountController(AccountService service) { this.service = service; }@PostMappingResponseEntity<AccountResponse> create(@Valid @RequestBody CreateAccountRequest req) {return ResponseEntity.status(201).body(service.create(req));}}@Service@Transactionalclass AccountService {private final AccountRepository repo;AccountService(AccountRepository repo) { this.repo = repo; }AccountResponse create(CreateAccountRequest req) {if (repo.existsByEmail(req.email())) throw new DuplicateEmailException();Account saved = repo.save(Account.from(req));return AccountResponse.from(saved);}}interface AccountRepository extends JpaRepository<Account, UUID> {boolean existsByEmail(String email);}
HLD tip: one box labeled 'Order Service' expands internally to these layers when interviewer asks implementation structure.
Real-world use
Real-world use cases
- Banking account service with strict audit and layered compliance checks.
- E-commerce catalog CRUD with caching at repository boundary.
- Healthcare API separating HIPAA logging in cross-cutting from clinical rules in service layer.
- Internal ERP modules maintained by teams familiar with n-tier patterns.
Best practices
- Keep controllers thin — no business rules in @RestController methods.
- Use DTOs at boundaries; never leak JPA entities to API responses.
- Define service interfaces for testability and future RPC extraction.
- Place caching on read paths at service or repository layer consistently.
- Centralize exception mapping and validation.
- Avoid circular dependencies between layers — extract shared kernel if needed.
Common mistakes
- Anemic domain model — all logic in services, entities are data bags without behavior.
- Skipping DTO layer — exposes DB schema and creates breaking API changes.
- Repository calling web layer — inverted dependency.
- God service class thousands of lines — split by use case.
- Mixing read and write concerns without CQRS when read queries become complex.
Advanced interview questions
Q1BeginnerName three layers in classic n-tier architecture.
Q2BeginnerWhy use DTOs between controller and service?
Q3IntermediateLayered vs hexagonal architecture?
Q4IntermediateWhere put caching in layered app?
Q5AdvancedLayer structure inside payment microservice?
Summary
Layered architecture organizes single-service code into presentation, logic, persistence. Dependency flows downward; domain rules live in service layer. DTOs protect API contracts from schema changes. Applies inside each microservice, not as whole-system topology. Hexagonal thinking improves testability and adapter swaps. Horizontal vs vertical scaling addresses deployment of these tiers next.