library / lib4574c7c0aa9da87b
Spring Microservices in Action, Second Edition
John Carnell Illary Huaylupo Sánchez
In a sentence
A hands-on, pattern-driven guide for Java/Spring developers to design, build, secure, deploy, and operationalize production-ready microservices using Spring Boot, Spring Cloud, Docker, and Kubernetes.
Spring Microservices in Action, Second Edition walks practicing Java developers step by step through the full lifecycle of a microservices architecture—from decomposing a monolithic application into bounded services, through containerization with Docker, centralized configuration with Spring Cloud Config, service discovery with Netflix Eureka, client-side resiliency with Resilience4j, API gateway routing with Spring Cloud Gateway, OAuth2/Keycloak security, asynchronous event-driven messaging with Spring Cloud Stream and Apache Kafka, distributed tracing with Sleuth and Zipkin, log aggregation with the ELK Stack, and finally automated build/deployment pipelines to Amazon EKS using Jenkins and Kubernetes. Every chapter introduces concrete design patterns, annotates real Spring Boot and Spring Cloud code, and ties the technology choices back to twelve-factor app principles, giving readers both the conceptual vocabulary and the working codebase needed to build, run, and evolve cloud-native microservices at scale.
The four lenses
- Science
- Statistics
- Systems
- Strategy
Tags
The model
A causal model describing how architectural design levers and operational engineering decisions in a Spring-based microservices system produce intermediate system-quality states (resilience, observability, security posture, deployment consistency) that in turn drive outcome metrics (system availability, delivery velocity, operational maintainability, and developer productivity).
Service Granularitydesign lever
The degree to which application functionality is decomposed into independently deployable units with narrowly scoped, well-defined business responsibilities and minimal data ownership overlap, ranging from coarse-grained (few, larger services) to fine-grained (many, smaller services).
Externalized Configurationdesign lever
The practice of completely separating all environment-specific configuration data (database URLs, credentials, feature flags) from the deployable service artifact and serving it from a centralized, versioned repository (filesystem, Git, or Vault) at service bootstrap time.
Service Discoverydesign lever
The architectural mechanism by which service instances dynamically register their physical location with a discovery registry (Netflix Eureka) and clients resolve service endpoints by logical name rather than hardcoded IP/port, enabling transparent addition and removal of instances.
Client-Side Load Balancingdesign lever
The pattern in which the service consumer maintains a local cache of available service instance locations (obtained from Eureka) and distributes outbound calls across healthy instances using a round-robin or zone-aware algorithm, eliminating reliance on a centralized load balancer.
Circuit Breaker Implementationdesign lever
The application of Resilience4j @CircuitBreaker annotations to remote resource calls, configuring ring buffer sizes, failure-rate thresholds, and wait durations so that sustained call failures cause the circuit to open and subsequent calls to fail fast rather than exhaust thread pools.
Fallback Strategydesign lever
The definition of alternative code paths invoked by Resilience4j when a circuit breaker opens or a call otherwise fails, enabling the service to return degraded but useful data rather than propagating an exception to the caller.
Bulkhead Implementationdesign lever
The use of Resilience4j @Bulkhead to compartmentalize concurrent calls to remote resources into isolated thread pools or semaphore limits, preventing a single slow downstream service from exhausting all container threads and collapsing the entire application.
Retry and Rate Limiter Patternsdesign lever
The application of Resilience4j @Retry to re-attempt transient failures up to a configured maximum with configurable wait durations, and @RateLimiter to cap the total number of calls per time period, preventing both retry storms and service overload.
API Gateway Routingdesign lever
The use of Spring Cloud Gateway as a single entry point that proxies all inbound service calls, applies predicate-based routing rules to map URL paths to downstream Eureka-registered service IDs, and enforces cross-cutting policies uniformly before forwarding requests.
Gateway Filter Engineeringdesign lever
The implementation of custom Spring Cloud Gateway pre-filters and post-filters to inject correlation IDs, validate authentication tokens, collect metrics, and augment HTTP response headers, enforcing consistent cross-cutting behavior across all services without modifying individual service code.
OAuth2 and Keycloak Securitydesign lever
The implementation of token-based authentication and role-based authorization using Keycloak as the identity provider, Spring Security and KeycloakWebSecurityConfigurerAdapter in each service, and JWT Bearer tokens propagated through the full service call chain via KeycloakRestTemplate.
Event-Driven Messagingdesign lever
The architectural choice to communicate state changes between services asynchronously via a Kafka topic using Spring Cloud Stream Source and Sink abstractions, decoupling producers from consumers and enabling durable, scalable, and replay-capable event propagation.
Distributed Cachingdesign lever
The use of Redis as a shared, externalized key-value cache layer that stores organization data retrieved by the licensing service, with cache invalidation triggered by Kafka messages emitted when organization state changes, reducing database load and improving response times.
Correlation ID Propagationdesign lever
The systematic injection and forwarding of a unique transaction-scoped identifier through HTTP headers, ThreadLocal storage, RestTemplate interceptors, and Spring Cloud Sleuth trace IDs, enabling end-to-end linking of log entries across all services involved in a single user transaction.
Distributed Tracingdesign lever
The instrumentation of services with Spring Cloud Sleuth to automatically generate and propagate trace and span IDs, integrated with Zipkin for visual transaction flow analysis and the ELK Stack for queryable, aggregated log storage, enabling performance profiling and failure diagnosis across service boundaries.
Immutable Deployment Pipelinedesign lever
The practice of building, testing, and packaging microservices as immutable Docker container images through a Jenkins-based CI/CD pipeline that deploys to Kubernetes on Amazon EKS, ensuring that every environment receives an identical, versioned artifact and that configuration drift is eliminated.
Service Coupling Degreepsychological state
The extent to which individual microservices have direct runtime dependencies on the physical location, internal data model, or synchronous availability of other services, ranging from tightly coupled (direct HTTP calls with shared data models) to loosely coupled (event-driven with independent data stores).
Configuration Drift Riskpsychological state
The probability that service instances running in production have diverged from their intended configuration state due to ad hoc manual changes, inconsistent environment promotion, or embedded properties in deployed artifacts, leading to unpredictable runtime behavior.
Resiliency Posturepsychological state
The overall capability of the microservices ecosystem to absorb partial failures—slow services, unreachable dependencies, thread exhaustion—without cascading those failures to consumers, maintaining partial availability and graceful degradation rather than total system collapse.
Security Posturepsychological state
The aggregate strength of authentication, authorization, token propagation, network zoning, and transport encryption controls protecting the microservices ecosystem from unauthorized access, credential exposure, and privilege escalation attacks.
System Observabilitypsychological state
The degree to which the internal state and transaction flow of the microservices ecosystem can be understood from its external outputs—structured logs with correlation IDs, distributed traces in Zipkin, and metrics dashboards in Grafana/Prometheus—enabling rapid diagnosis of production issues.
System Availabilityoutcome metric
The measured uptime and request success rate of the overall microservices application as experienced by end users, reflecting the cumulative effect of resiliency patterns, fault isolation, health monitoring, and rapid instance recovery mechanisms.
Delivery Velocityoutcome metric
The rate at which new features, bug fixes, and configuration changes can be safely built, tested, and deployed to production, enabled by independent service deployability, immutable container images, and automated CI/CD pipelines.
Operational Maintainabilityoutcome metric
The ease with which operators and developers can understand, diagnose, reconfigure, scale, and recover the running microservices ecosystem, determined by the quality of observability tooling, configuration management automation, and deployment pipeline repeatability.
Developer Productivityoutcome metric
The efficiency and confidence with which individual developers can build, test, and evolve their microservice in isolation, supported by Spring Boot's auto-configuration and embedded server model, Spring Cloud's annotation-driven infrastructure abstractions, and reproducible Docker Compose environments.
How they connect
- service granularity − influences service coupling
- service granularity → influences developer productivity
- externalized configuration − influences configuration drift risk
- externalized configuration → influences delivery velocity
- service discovery − influences service coupling
- service discovery → influences system availability
- client side load balancing → influences resiliency posture
- circuit breaker implementation → influences resiliency posture
- fallback strategy → influences resiliency posture
- bulkhead implementation → influences resiliency posture
- resiliency posture → predicts system availability
- retry and rate limiter → influences resiliency posture
- api gateway routing → influences security posture
- api gateway routing → influences operational maintainability
- gateway filter engineering → influences correlation id propagation
- oauth2 keycloak security → influences security posture
- security posture → influences system availability
- event driven messaging − influences service coupling
- event driven messaging → influences resiliency posture
- distributed caching → influences system availability
- correlation id propagation → mediates observability
- distributed tracing → influences observability
- observability → predicts operational maintainability
- immutable deployment pipeline − influences configuration drift risk
- immutable deployment pipeline → influences delivery velocity
- configuration drift risk − influences system availability
- service coupling − influences system availability
- service coupling − influences delivery velocity
- developer productivity → predicts delivery velocity
The story
The reader An experienced Java/Spring developer who wants to build modern, cloud-deployable microservices but feels overwhelmed by the operational complexity—service discovery, configuration, resiliency, security, tracing, and deployment—that lies beyond writing the business logic.
External problem
The developer knows how to write a Spring Boot service but cannot reliably decompose monoliths, wire together the cloud infrastructure patterns, or deploy and operate a distributed system in production.
Internal problem
They feel anxious and out of depth: every tutorial covers one pattern in isolation, yet real systems require all patterns working together, and a mistake in production means cascading failures, security breaches, or undebuggable outages.
Philosophical problem
It is wrong that powerful cloud-native patterns developed by companies like Netflix, HashiCorp, and Google are inaccessible to the average developer, forcing teams to either reinvent complex infrastructure or remain stuck in brittle monoliths.
The plan
- Understand microservice architecture trade-offs versus monoliths and learn the full catalog of patterns (core development, routing, resiliency, security, logging/tracing, build/deployment).
- Apply the twelve-factor app methodology to design cloud-native services from the start.
- Build and containerize Spring Boot services with Docker and Docker Compose, enabling reproducible environments.
- Centralize and externalize configuration using Spring Cloud Config Server backed by filesystem, Git, or HashiCorp Vault, with symmetric encryption for sensitive properties.
- Register services with Netflix Eureka and implement client-side load balancing using Spring Cloud LoadBalancer and the Feign client.
- Protect consumers from cascading failures by wrapping remote calls with Resilience4j circuit breakers, bulkheads, retries, rate limiters, and fallbacks.
- Route all external traffic through Spring Cloud Gateway, injecting correlation IDs via pre-filters and returning them via post-filters to enable end-to-end tracing.
- Secure services with Keycloak and OAuth2/JWT: register clients, define roles, propagate Bearer tokens across the entire call chain.
- Decouple services with asynchronous event-driven messaging via Spring Cloud Stream and Apache Kafka; implement distributed caching with Redis.
- Implement distributed tracing with Spring Cloud Sleuth and Zipkin, and aggregate logs with the ELK Stack.
- Deploy the complete architecture to Amazon EKS using a Jenkins-based CI/CD pipeline with Kubernetes manifests.
Success
- Confidently decompose any monolithic application into appropriately sized, independently deployable microservices.
- Operate a resilient, self-healing service ecosystem where individual service failures do not cascade to the whole system.
- Ship configuration changes, security updates, and new features without redeploying or restarting unaffected services.
- Debug any distributed transaction end-to-end using correlation IDs, Sleuth trace IDs, Zipkin, and Kibana dashboards.
- Deploy and scale containerized services on Kubernetes with a fully automated CI/CD pipeline, achieving continuous delivery to production.
At stake
- Remain locked in a brittle monolith that cannot scale independently, requires full redeployment for every change, and risks total outage from any single component failure.
- Build microservices that are tightly coupled through synchronous calls, causing cascading failures that take down entire application ecosystems.
- Expose services with hardcoded credentials, no token propagation, and no network zoning, leaving the architecture vulnerable to security breaches.
- Operate distributed services blindly—without correlation IDs, distributed tracing, or log aggregation—making production incidents nearly impossible to diagnose.
- Deploy services manually with configuration drift across environments, leading to unpredictable behavior and 'works on my machine' failures in production.
Related in the library
- Spring AI in Action
- AI Agents and Applications (with LangChain, LangGraph, and MCP)
- An a to Z Guidebook on Microservices An Introduction Explaining Microservices and Their Patterns Microservices Patterns Book
- Bootstrapping Microservices, Second Edition (MEAP) With Docker, Kubernetes, GitHub Actions, and Terraform
- Just Use Postgres