Layered Architecture
Layered architecture separates concerns into distinct layers. Each layer only communicates with the layer directly below it.
The Three Core Layers
┌─────────────────────────┐
│ Controller │ -- HTTP requests/responses
├─────────────────────────┤
│ Service │ -- Business logic
├─────────────────────────┤
│ Repository │ -- Database access
├─────────────────────────┤
│ Database │ -- Data storage
└─────────────────────────┘
Layer Responsibilities
| Layer | Responsibility | Knows About |
|---|---|---|
| Controller | Handle HTTP, validate input, return responses | Service layer |
| Service | Business logic, transactions, orchestration | Repository layer |
| Repository | CRUD operations, query database | Database/Entities |
| Model | Data structures, entities, DTOs | Nothing (pure data) |
Code Example — Layer by Layer
Controller Layer:
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping("/{id}")
public ResponseEntity<ProductDto> getProduct(@PathVariable Long id) {
ProductDto product = productService.getProduct(id);
return ResponseEntity.ok(product);
}
@PostMapping
public ResponseEntity<ProductDto> createProduct(@RequestBody CreateProductRequest request) {
ProductDto created = productService.createProduct(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}
Service Layer:
@Service
public class ProductService {
private final ProductRepository productRepository;
private final ProductMapper productMapper;
public ProductService(ProductRepository productRepository, ProductMapper productMapper) {
this.productRepository = productRepository;
this.productMapper = productMapper;
}
public ProductDto getProduct(Long id) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Product not found"));
return productMapper.toDto(product);
}
@Transactional
public ProductDto createProduct(CreateProductRequest request) {
Product product = productMapper.toEntity(request);
Product saved = productRepository.save(product);
return productMapper.toDto(saved);
}
}
Repository Layer:
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByCategoryId(Long categoryId);
List<Product> findByNameContainingIgnoreCase(String name);
}
Benefits of Layered Architecture
- Separation of concerns — each layer has one job
- Testability — mock individual layers in tests
- Maintainability — changes in one layer don't ripple
- Team collaboration — different developers work on different layers
Common Anti-Patterns
- Fat Controller — business logic in controller
- Service calling Service — circular dependencies
- Repository with logic — business rules in repository
- Skipping layers — controller directly calling repository
Interview Focus
Interview Questions
Q: What happens if you put business logic in a controller?
- Controller becomes hard to test
- Logic can't be reused by other entry points (CLI, message consumers)
- Violates Single Responsibility Principle
Q: Can services call other services?
- Yes, but keep it minimal to avoid circular dependencies
- Better to extract shared logic into a dedicated service
Q: When would you skip the repository layer?
- For read-only queries that don't need JPA entities
- When calling external APIs (use a client/service instead)
- For simple lookups from cache
Practical Example — Amazon Order Flow
OrderController
└── orderService.createOrder(request)
├── userService.validateUser(userId)
├── inventoryService.checkStock(items)
├── pricingService.calculateTotal(items)
├── orderRepository.save(order)
└── messageService.sendOrderConfirmation(order)
Each service handles its own concern. The OrderService orchestrates the flow.
Practice Problems
Design and implement a solution for Layered Architecture in a backend system. Consider scalability, error handling, and production readiness.
Solution
// Layered Architecture implementation
// Key aspects: validation, error handling, logging, testing
public class LayeredArchitecture {
// Production-ready implementation
}Identify and handle edge cases for Layered Architecture. What happens under high load, with invalid input, or during failures?
Solution
// Edge case handling:
// 1. Null/empty input -> validation
// 2. High load -> rate limiting, queuing
// 3. Failures -> retries, circuit breaker
// 4. Concurrent access -> locks, idempotencyWrite a testing strategy for Layered Architecture. Include unit tests, integration tests, and performance tests.
Solution
// Test plan:
// - Unit: 80% coverage target
// - Integration: API contracts
// - Performance: latency, throughput
// - Chaos: failure injectionQuiz
1. Which layer handles business logic?
2. What is a "fat controller" anti-pattern?
3. What is the primary purpose of Layered Architecture?
4. What is a common mistake when implementing Layered Architecture?
Flashcards
Question
What are the 3 main layers?
Click to reveal answer
Answer
Controller (HTTP), Service (business logic), Repository (database)
Question
What is a fat controller?
Click to reveal answer
Answer
A controller that contains business logic instead of delegating to services
Question
What is Layered Architecture?
Click to reveal answer
Answer
Layered Architecture is a key concept in backend development.
Question
When to use Layered Architecture?
Click to reveal answer
Answer
Use Layered Architecture when building production systems that require reliability, scalability, and maintainability.
Question
Layered Architecture best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.Three core layers: Controller → Service → Repository
- 2.Each layer has a single responsibility
- 3.Controller handles HTTP, Service handles logic, Repository handles data
- 4.Avoid fat controllers and circular service dependencies
Interview Tips
- •Explain what each layer does and why separation matters
- •Know common anti-patterns like fat controllers
- •Be ready to design a layered architecture for a given problem
Cheat Sheet
Layered Architecture
- Controller: HTTP requests/responses, input validation
- Service: Business logic, transactions, orchestration
- Repository: CRUD operations, database queries
- Rule: Each layer only calls the layer below it