Skip to content
intermediatePhase ·

Layered Architecture

Learn the controller-service-repository layered pattern.

40m
0 problems
Topic Progress0%

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

  1. Separation of concerns — each layer has one job
  2. Testability — mock individual layers in tests
  3. Maintainability — changes in one layer don't ripple
  4. 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

0/3solved
Implement Layered Architecture

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
}
Layered Architecture Edge Cases

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, idempotency
Layered Architecture Testing Strategy

Write 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 injection

Quiz

1. Which layer handles business logic?

Question 1 options

2. What is a "fat controller" anti-pattern?

Question 2 options

3. What is the primary purpose of Layered Architecture?

Question 3 options

4. What is a common mistake when implementing Layered Architecture?

Question 4 options

Flashcards

Question

What are the 3 main layers?

Answer

Controller (HTTP), Service (business logic), Repository (database)

Question

What is a fat controller?

Answer

A controller that contains business logic instead of delegating to services

Question

What is Layered Architecture?

Answer

Layered Architecture is a key concept in backend development.

Question

When to use Layered Architecture?

Answer

Use Layered Architecture when building production systems that require reliability, scalability, and maintainability.

Question

Layered Architecture best practices

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