
by Zelkulon05 March 20251 min read
Structure, connect and secure microservices with Spring Boot β a complete practical guide with real code examples and architecture diagrams.
What are Microservices?
A microservice architecture splits an application into small, independently deployable services. Each service is responsible for exactly one business domain β the Bounded Context from Domain-Driven Design.

Each service has its own database β this prevents tight coupling and allows each service to choose its own database type.
Project Structure
order-service/
βββ src/main/java/com/zelkulon/order/
β βββ OrderServiceApplication.java
β βββ controller/
β β βββ OrderController.java
β βββ service/
β β βββ OrderService.java
β β βββ OrderServiceImpl.java
β βββ repository/
β β βββ OrderRepository.java
β βββ model/
β β βββ Order.java
β β βββ OrderItem.java
β βββ dto/
β βββ OrderRequest.java
β βββ OrderResponse.java
βββ src/main/resources/
βββ application.ymlThe Domain Model
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
private String customerId;
@Enumerated(EnumType.STRING)
private OrderStatus status;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<OrderItem> items = new ArrayList<>();
private BigDecimal totalAmount;
@PrePersist
void onCreate() {
this.createdAt = LocalDateTime.now();
this.status = OrderStatus.PENDING;
}
}Service-to-Service Communication with Feign
With Spring Cloud OpenFeign, another microservice behaves like a local service object:
@FeignClient(name = "product-service", url = "${services.product.url}")
public interface ProductServiceClient {
@GetMapping("/api/products/{productId}")
ProductDto getProduct(@PathVariable String productId);
@PutMapping("/api/products/{productId}/stock")
void reduceStock(@PathVariable String productId,
@RequestParam int quantity);
}Circuit Breaker with Resilience4j
Circuit Breakers prevent cascading failures when a service is unreachable:
@Service
public class OrderServiceImpl implements OrderService {
@Override
public OrderResponse placeOrder(OrderRequest request) {
CircuitBreaker cb = circuitBreakerFactory.create("product-service");
boolean available = cb.run(
() -> checkProductAvailability(request.getItems()),
throwable -> {
log.warn("ProductService unreachable β fallback active");
return false;
}
);
if (!available) throw new OrderException("Products unavailable");
return processOrder(request);
}
}Saga Pattern for Distributed Transactions
In microservices there are no global database transactions. The Saga Pattern solves this problem:

Summary
- One service = one business domain β no god services
- Own database per service prevents data coupling
- Circuit Breakers are mandatory for production-ready systems
- API Gateway centralizes authentication and routing
- Saga Pattern solves the problem of distributed transactions