Spring Boot Tutorial
Microservices Architecture with Spring Boot
Microservices split an application into small, independently deployable services, each owning one business capability and its own data — catalogue, orders, payments, notifications. Done well, teams deploy independently, services scale separately, and failures stay contained. Done badly, you get a "distributed monolith": all the complexity of a network with none of the independence.
Spring Boot is the most widely used framework for Java microservices, and Spring Cloud adds the distributed-systems building blocks. This lesson explains when microservices are (and are not) the right choice, how to find service boundaries, how services communicate, how data is split, and which Spring Cloud components solve which problems — setting up the rest of this module.
Monolith, Modular Monolith or Microservices?
Most new products should start as a well-structured monolith — one deployable with clear internal modules (Spring Modulith helps enforce them). Microservices pay off when several teams need to deploy independently, parts of the system have very different scaling or reliability needs, or the codebase has become too large for one team. They add network latency, partial failures, distributed data consistency, and much more operational work: CI/CD, monitoring, tracing and on-call for every service.
Finding Service Boundaries
Use Domain-Driven Design's bounded contexts: areas of the business with their own language and rules, such as Catalogue, Ordering, Payments, Learning Progress. A good service boundary means most changes touch one service, each service owns its data exclusively (no shared database tables), and services communicate through well-defined APIs or events. If two services always change and deploy together, they probably belong together.
Communication Styles
Synchronous calls (REST with HTTP service clients, gRPC) are simple and give immediate answers, but couple availability: if Payments is down, checkout fails. Asynchronous messaging (Kafka, RabbitMQ) decouples services in time: Ordering publishes OrderPlaced and Notifications reacts whenever it can. Mature systems use both: synchronous queries where an immediate answer is required, events for everything else.
The Spring Cloud Toolbox
Spring Cloud 2025.1 ("Oakwood", for Spring Boot 4) provides:
- Spring Cloud Config — centralised, versioned configuration for all services.
- Spring Cloud Netflix Eureka and LoadBalancer — service registry and client-side load balancing (on Kubernetes, the platform often provides this instead).
- Spring Cloud Gateway — the API gateway: routing, security, rate limiting at the edge.
- Spring Cloud Circuit Breaker — Resilience4j integration for fault tolerance.
- Spring Cloud Stream — portable event-driven messaging over Kafka and RabbitMQ.
- Spring Cloud Kubernetes, Vault, Contract, Function — platform integration, secrets, consumer-driven contract tests, serverless functions.
- Observability (Micrometer + OpenTelemetry) and security (OAuth2 resource servers) come from Spring Boot and Spring Security.
Examples
An example system and its services
┌──────────────────────┐
Browser/App → │ api-gateway (8080) │ Spring Cloud Gateway, JWT validation, rate limits
└──────────┬───────────┘
┌────────────────┼──────────────────────┐
▼ ▼ ▼
catalog-service order-service ──HTTP──▶ payment-service
(PostgreSQL) (PostgreSQL) (PostgreSQL)
│ OrderPlaced / PaymentCompleted events (Kafka)
▼
notification-service (email, push)
Supporting: config-server (8888), discovery-server/Eureka (8761),
auth-server (Spring Authorization Server), Prometheus, Grafana, Jaeger
(Each service is its own Spring Boot application, repository/module, database and deployment.)
Importing the Spring Cloud BOM
<properties>
<spring-cloud.version>2025.1.2</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(Spring Cloud 2025.1.x is the release train compatible with Spring Boot 4.0/4.1. Always check the compatibility table before upgrading either.)
A synchronous call between services with an HTTP service client
// order-service calling payment-service
@HttpExchange("/api/payments")
public interface PaymentClient {
@PostExchange
PaymentResult charge(@RequestBody ChargeRequest request);
}
@SpringBootApplication
@ImportHttpServices(group = "payments", types = PaymentClient.class)
public class OrderServiceApplication { ... }
# application.yml (service name resolved by the load balancer / Kubernetes DNS)
spring:
http:
serviceclient:
payments:
base-url: http://payment-service
read-timeout: 3s
POST http://payment-service/api/payments -> 201 {"paymentId":"pay_91x","status":"CAPTURED"}
Common Mistakes
- Starting a new product with a dozen microservices before the domain is understood.
- Sharing one database between services, coupling them through tables and schemas.
- Building long synchronous call chains (A → B → C → D), where one slow service stalls everything.
- Splitting by technical layer ("user-controller-service", "user-db-service") instead of business capability.
- Adopting microservices without automated CI/CD, centralised logging, tracing and monitoring.
Key Points to Remember
- Microservices trade simplicity for independent deployment and scaling; start with a modular monolith unless you need them.
- Draw boundaries around business capabilities (bounded contexts); each service owns its data.
- Use synchronous calls where an immediate answer is needed and events for everything else.
- Spring Cloud 2025.1 (Oakwood) provides config, discovery, gateway, circuit breakers and streaming for Spring Boot 4.
- Observability and automation are prerequisites, not extras.
Practice the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Use your local JDK or project IDE for these examples. Codelab currently runs Python and HTML/CSS/JavaScript; framework examples may need project dependencies.