What are Spring Cloud Microservices Best Practices in 2026
Problem
I returned to a microservices project after two years away. When I tried to start the application, I got warnings about deprecated Netflix OSS components:
2026-03-11 10:15:23 WARN [main] o.s.c.n.a.s.a.RibbonAutoConfiguration - Ribbon is in maintenance mode. Use Spring Cloud LoadBalancer instead.2026-03-11 10:15:24 WARN [main] o.s.c.n.zuul.ZuulProxyAutoConfiguration - Zuul is in maintenance mode. Use Spring Cloud Gateway instead.2026-03-11 10:15:25 WARN [main] o.s.c.n.h.HystrixCircuitBreakerConfiguration - Hystrix is in maintenance mode. Use Resilience4j instead.I was confused. These components worked fine before. What changed? And what should I use now?
What Happened?
The microservices landscape shifted significantly. Netflix OSS components (Hystrix, Zuul, Ribbon) that were once the standard are now deprecated or in maintenance mode.
Hereβs the modern mapping:
DEPRECATED MODERN ALTERNATIVE----------- ------------------Hystrix --> Resilience4j (circuit breaker)Zuul --> Spring Cloud Gateway (API gateway)Ribbon --> Spring Cloud LoadBalancerArchaius --> Spring Cloud ConfigEureka --> Eureka (still maintained) or Kubernetes ServicesI made the mistake of using old tutorials. Many online courses still reference deprecated Netflix OSS components.
Environment
- Spring Boot 3.2.x
- Spring Cloud 2023.0.x
- Java 21
- Kubernetes (optional)
The Solution
I learned to focus on essential patterns first. Hereβs my approach.
Step 1: Start with Essential Patterns Only
I used to implement all Spring Cloud patterns immediately. That was wrong. Now I start with the minimum viable architecture:
+-------------------+ +-------------------+| API Gateway | | Config Server || Spring Cloud | | Spring Cloud || Gateway | | Config |+--------+----------+ +-------------------+ | | Service Discovery (Eureka or K8s) | +----+----+ +---------+ +---------+ | Service A| | Service B| | Service C| +----------+ +----------+ +----------+Essential patterns (implement these first):
- Service Discovery - Never hardcode service URLs
- API Gateway - Single entry point for all clients
- Centralized Configuration - Externalize all environment-specific config
- Circuit Breaker - Prevent cascading failures
Step 2: Use Modern Components
I replaced deprecated components in my pom.xml:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version></parent>
<properties> <spring-cloud.version>2023.0.0</spring-cloud.version> <resilience4j.version>2.2.0</resilience4j.version></properties>
<dependencies> <!-- Service Discovery --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
<!-- API Gateway (NOT Zuul) --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
<!-- Centralized Config --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
<!-- Circuit Breaker (NOT Hystrix) --> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot3</artifactId> <version>${resilience4j.version}</version> </dependency></dependencies>Step 3: Configure Service Discovery
I set up Eureka for service discovery. The key point: never hardcode URLs.
spring: application: name: order-service
eureka: client: service-url: defaultZone: http://discovery-server:8761/eureka/ instance: prefer-ip-address: true health-check-url-path: /actuator/healthThen I used @LoadBalanced RestTemplate for service-to-service calls:
@SpringBootApplication@EnableDiscoveryClient@RestControllerpublic class OrderServiceApplication {
@Bean @LoadBalanced // Spring Cloud LoadBalancer, NOT Ribbon public RestTemplate restTemplate() { return new RestTemplate(); }
@GetMapping("/orders/{id}") public Order getOrder(@PathVariable Long id) { // Use logical service name, NOT hardcoded URL return restTemplate().getForObject( "http://inventory-service/api/inventory/" + id, Order.class ); }}Step 4: Add Circuit Breakers
I added Resilience4j for circuit breakers. This prevents cascading failures.
@Servicepublic class OrderService {
@CircuitBreaker(name = "inventoryService", fallbackMethod = "fallbackInventory") public Inventory checkInventory(Long productId) { return restTemplate.getForObject( "http://inventory-service/api/inventory/" + productId, Inventory.class ); }
// Fallback when inventory service is down public Inventory fallbackInventory(Long productId, Exception e) { return new Inventory(productId, 0, false); }}Configuration for the circuit breaker:
resilience4j: circuitbreaker: instances: inventoryService: sliding-window-size: 10 failure-rate-threshold: 50 wait-duration-in-open-state: 10s permitted-number-of-calls-in-half-open-state: 3Step 5: Set Up API Gateway
I used Spring Cloud Gateway instead of deprecated Zuul:
spring: cloud: gateway: routes: - id: order-service uri: lb://order-service # Load-balanced via discovery predicates: - Path=/api/orders/** filters: - name: CircuitBreaker args: name: orderCircuitBreaker - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20Why This Matters
I made several mistakes before learning these best practices:
Mistake #1: Using deprecated Netflix OSS components These have no active development. No Spring Boot 3 support. Security vulnerabilities pile up.
Mistake #2: Implementing all patterns at once I tried to add distributed tracing, message queues, and service mesh on day one. Debugging was a nightmare.
Mistake #3: Ignoring Kubernetes-native solutions When deploying to Kubernetes, I duplicated functionality. Kubernetes already provides service discovery (Services) and configuration (ConfigMaps/Secrets).
When to Use Kubernetes-Native Solutions
If deploying to Kubernetes, consider using:
apiVersion: v1kind: Servicemetadata: name: order-servicespec: ports: - port: 8080 selector: app: order-service---apiVersion: v1kind: ConfigMapmetadata: name: order-service-configdata: spring.profiles.active: "kubernetes"Spring Cloud Kubernetes provides seamless integration:
spring: cloud: kubernetes: discovery: enabled: true config: enabled: trueCommon Mistakes to Avoid
- Hardcoding service URLs - Always use service discovery
- Missing circuit breakers - Every service-to-service call needs one
- Skipping distributed tracing - Add Micrometer + Zipkin from day one
- Synchronous communication everywhere - Use message queues for decoupling
- Ignoring configuration management - Externalize all environment-specific config
Architecture Checklist
Before considering my microservices architecture complete:
- Service Discovery configured (Eureka or Kubernetes Services)
- API Gateway implemented (Spring Cloud Gateway, NOT Zuul)
- Centralized Configuration (Config Server or Kubernetes ConfigMaps)
- Circuit Breakers at service boundaries (Resilience4j, NOT Hystrix)
- Health checks exposed (Spring Boot Actuator)
- All hardcoded URLs removed
- Using Spring Cloud LoadBalancer (NOT Ribbon)
- Spring Boot 3.x compatible dependencies
Summary
I learned that modern Spring Cloud microservices best practices prioritize:
- Modern components over deprecated Netflix OSS (Resilience4j, Spring Cloud Gateway, Spring Cloud LoadBalancer)
- Essential patterns first, then add advanced features incrementally
- Kubernetes-native solutions when deploying to Kubernetes
The key insight: donβt over-engineer. Start with service discovery, API gateway, centralized configuration, and circuit breakers. Add distributed tracing, message queues, and service mesh only when you actually need them.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- π¨βπ» Spring Cloud Documentation
- π¨βπ» Spring Cloud Netflix OSS Status
- π¨βπ» Resilience4j Documentation
- π¨βπ» Spring Cloud Gateway Reference
- π¨βπ» Reddit: Spring Cloud and Microservices Discussion
Oh, and if you found these resources useful, donβt forget to support me by starring the repo on GitHub!
Comments