Microservices — an architectural style where an application is decomposed into a collection of small, autonomous services, each running in its own process and communicating via lightweight mechanisms such as HTTP/REST or message brokers.
System Design Context: Microservices evolved from the limitations of monolithic architectures where a single codebase handled all business functions. As systems grew, monoliths became difficult to scale, deploy, and maintain. Microservices solve this by breaking the system into bounded contexts aligned with business domains (Domain-Driven Design).
Key Principles:
Production Components:
1// User Service — a complete microservice example2@RestController3@RequestMapping("/api/users")4@Validated5public class UserController {67 private final UserService userService;8 private final CircuitBreaker circuitBreaker;910 public UserController(UserService userService,11 CircuitBreakerRegistry registry) {12 this.userService = userService;13 this.circuitBreaker = registry.circuitBreaker("userService");14 }1516 @GetMapping("/{id}")17 public ResponseEntity<UserDTO> getUser(@PathVariable @Positive Long id) {18 UserDTO user = Decorators.ofCallable(() -> userService.findById(id))19 .withCircuitBreaker(circuitBreaker)20 .withRetry(Retry.of("retry",21 RetryConfig.custom().maxAttempts(3).build()))22 .decorate()23 .execute();24 return ResponseEntity.ok(user);25 }2627 @PostMapping28 @ResponseStatus(HttpStatus.CREATED)29 public UserDTO createUser(@Valid @RequestBody CreateUserRequest request) {30 return userService.create(request);31 }32}3334// Service with event publishing35@Service36@Transactional37public class UserService {3839 private final UserRepository userRepository;40 private final KafkaTemplate<String, UserEvent> kafkaTemplate;4142 public UserDTO create(CreateUserRequest request) {43 User user = new User(request.name(), request.email());44 User saved = userRepository.save(user);45 kafkaTemplate.send("user-events",46 new UserCreatedEvent(saved.getId(), saved.getEmail()));47 return UserDTO.from(saved);48 }4950 public UserDTO findById(Long id) {51 return userRepository.findById(id)52 .map(UserDTO::from)53 .orElseThrow(() -> new UserNotFoundException(id));54 }55}
Scaling Patterns:
Common Pitfalls:
Monitoring & Observability:
Benefits: