
Microservices mit Spring Boot strukturieren, kommunizieren lassen und absichern – ein vollständiger Praxisleitfaden mit echten Code-Beispielen und Architekturdiagrammen.
Was sind Microservices?
Eine Microservice-Architektur teilt eine Anwendung in kleine, unabhängig deploybare Dienste auf. Jeder Service ist für genau eine fachliche Domäne verantwortlich – dem Bounded Context aus dem Domain-Driven Design.

Jeder Service hat eine eigene Datenbank – das verhindert enge Kopplung und ermöglicht, dass jeder Service seinen eigenen Datenbanktyp wählen kann.
Projektstruktur
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.ymlDas Domain-Modell
@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-zu-Service-Kommunikation mit Feign
Mit Spring Cloud OpenFeign verhält sich ein anderer Microservice wie ein lokales Service-Objekt:
@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 mit Resilience4j
Circuit Breaker verhindern Kaskadenausfälle, wenn ein Service nicht erreichbar ist:
@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 nicht erreichbar – Fallback aktiv");
return false;
}
);
if (!available) throw new OrderException("Produkte nicht verfügbar");
return processOrder(request);
}
}Saga-Pattern für verteilte Transaktionen
Bei Microservices gibt es keine globalen Datenbank-Transaktionen. Das Saga-Pattern löst dieses Problem:

Fazit
- Ein Service = eine fachliche Domäne – keine God-Services
- Eigene Datenbank pro Service verhindert Datenkopplung
- Circuit Breaker sind Pflicht für produktionsreife Systeme
- API Gateway zentralisiert Authentifizierung und Routing
- Saga-Pattern löst das Problem verteilter Transaktionen