DevNotes
Support
Spring Boot · Chapter 25

Spring Boot Microservices

Monolith vs microservices, database per service, sync vs async communication, Eureka, API Gateway, Config Server, OpenFeign, load balancing, Resilience4j, tracing, Saga and idempotency.

◷ 8 min read§ 25 sections? 11 interview questions{ } 1 code examples

#Introduction

Microservices are one of the most important topics for 5–10 years Java Spring Boot developers — most large enterprises (Netflix, Amazon, Uber, Spotify, LinkedIn, Walmart, PayPal, Adobe) have moved from monolithic applications to microservices.

Interviewers frequently ask: What are microservices? Monolith vs microservices? What are service discovery and Eureka? What are an API gateway and a config server? What is OpenFeign? What are circuit breakers and Resilience4j? What is distributed tracing? What is the Saga pattern? What is idempotency? How do microservices communicate, and how do transactions work across them?

#What is a Monolithic Application?

One large application where every module is deployed together:

One application
User moduleOrder modulePayment moduleInventory moduleNotification module
Database
One shared database
E-commerce monolith — everything runs inside one application

Problems with a Monolith

Suppose only the payment module has high traffic. You still have to scale the entire application — more CPU, more memory, higher cost. Other problems: slow deployments, a large codebase, difficult scaling and maintenance, technology lock-in, and one failure can affect the whole application.

#What are Microservices?

Microservices split the application into multiple independent services:

Client
Gateway
User · Order · Payment · Inventory · Notification services
Each service has its own database

Each service has its own code, its own deployment, its own database, and can scale independently.

Monolith vs Microservices

Interview favourite.

MonolithMicroservices
Single applicationMultiple applications
Single deploymentIndependent deployments
Shared databaseDatabase per service
Scale the entire appScale only the required service
Easier to startBetter for large systems
Tightly coupledLoosely coupled

#Typical Microservice Architecture

Internet
Load balancer
API gateway
User MS · Order MS · Payment MS · Inventory MS
User DB · Order DB · Payment DB · Inventory DB

#Why Separate Databases?

❌ Wrong: all services → one database. Problems: tight coupling, schema conflicts and shared failures.

✅ Correct: User Service → User database; Order Service → Order database. Each service owns its data.

#Service Communication

Microservices communicate using REST APIs, gRPC, Kafka or RabbitMQ — in two styles:

Synchronous (e.g. REST)Asynchronous (e.g. Kafka)
Order → Payment → Inventory over HTTPOrder → Kafka topic → Notification
✅ Simple, immediate response✅ Loose coupling, better scalability and fault tolerance
❌ Tight runtime dependency, higher latency, cascading failures❌ Eventual consistency, more operational complexity

#Service Discovery

Eureka Server

Spring Cloud Netflix Eureka:

Payment Service starts
Registers with Eureka (status UP)
Order Service asks Eureka for payment-service
Gets an address
Calls Payment Service

Eureka maintains a registry of available service instances.

#API Gateway

Interview favourite. Instead of the client calling User, Order and Payment services directly:

Client
API gateway
Microservices

Gateway responsibilities: routing, authentication, authorization, rate limiting, logging, SSL termination and request filtering. A popular choice is Spring Cloud Gateway.

Client
Gateway
Authentication
Routing
Service

#Config Server

Imagine 100 microservices that all need a database URL, JWT secret, Kafka URL and Redis URL. Storing these in every application is a bad idea. Instead:

Git repository
Config Server
All microservices
Centralized configuration

#OpenFeign

Interview favourite. Without Feign you write manual HTTP calls with RestTemplate/RestClient. With Feign:

Java
@FeignClient(name = "payment-service")
public interface PaymentClient {

    @PostMapping("/pay")
    PaymentResponse pay(@RequestBody PaymentRequest request);
}

Spring generates the client implementation automatically (enable it with @EnableFeignClients). Benefits: less boilerplate, better readability, and integration with service discovery and load balancing.

#Load Balancing

Payment Service runs as instances 1, 2 and 3; the client-side load balancer chooses one instance per call. Modern Spring Cloud uses Spring Cloud LoadBalancer (it replaced Netflix Ribbon).

#Circuit Breaker

One of the most asked interview questions.

Problem: Order Service calls Payment Service, which is down. Order keeps retrying, threads become blocked, and the entire system slows down.

Resilience4j Circuit Breaker

CLOSED — calls flow normally
OPEN — calls are blocked / fallback
HALF_OPEN — a few test calls allowed
Test calls succeed?
back to CLOSED
back to OPEN

Benefits: prevents cascading failures, improves resilience and enables graceful recovery.

Retry

Sometimes failures are temporary: call failed → retry → retry → success. Resilience4j supports configurable retry policies (with backoff).

Timeout

Never wait forever. E.g. Order Service waits at most 2 seconds for Payment Service → timeout → fallback. Always configure sensible timeouts.

Bulkhead

Problem: a slow Payment Service consumes all threads and the entire application blocks. A bulkhead isolates dependencies (separate thread pools or concurrency limits for payment, inventory, notification), so one failing dependency can't consume all resources.

#Distributed Tracing

One request flows through Gateway → Order → Payment → Inventory → Notification. How do you trace it? Use OpenTelemetry, Zipkin or Jaeger: each request receives a trace ID that's propagated to every service, so the entire request can be followed end to end.

#Event-Driven Architecture

Instead of Order calling Notification directly, Order publishes an event:

Order Service
Publish event
Kafka
Notification Service
Email
Services become loosely coupled

#Saga Pattern

Interview favourite. Traditional database transactions don't span multiple independent microservices. Instead, use a Saga:

Create order
Reserve inventory
Take payment — success?
Ship order
Cancel inventory → cancel order

Each service performs a compensating action to undo its local step.

Choreography vs Orchestration

ChoreographyOrchestration
Each service reacts to events (Order → Inventory → Payment → Shipping)A central saga orchestrator tells Order, Payment, Inventory and Shipping what to do
No central coordinatorOne coordinator controls the workflow

#Distributed Transactions

Microservices generally avoid two-phase commit (2PC) because of its complexity and impact on availability. The preferred approach:

Local transaction
Publish event
Next service
Compensating action on failure

#Idempotency

Interview favourite. A user clicks Pay Now five times — payment should occur only once.

Request with idempotency key
Already processed?
Return the previous result
Process and store the result

Common in payment systems.

#Database Per Service

❌ Never let Order Service query the Payment database directly. ✅ Order Service calls the Payment API. Each service owns its database.

#Independent Deployment

Deploying Payment v2 requires no deployment of Order Service.

#Common Spring Cloud Components

ComponentPurpose
EurekaService discovery
Spring Cloud GatewayAPI gateway
Config ServerCentralized configuration
OpenFeignDeclarative REST client
Spring Cloud LoadBalancerClient-side load balancing
Resilience4jCircuit breaker, retry, bulkhead
Spring Cloud BusConfiguration refresh events
OpenTelemetryDistributed tracing

#Internal Request Flow

Client
API gateway
Authentication
Service discovery
Load balancer
Microservice
Database
Kafka event
Other services

#Common Mistakes

  • Shared database — each service should own its own data.
  • Synchronous calls everywhere — too many REST hops increase latency and cause cascading failures; use async messaging where appropriate.
  • No circuit breaker — a failing downstream service can take down the whole system.
  • No timeouts — remote calls without connection/read timeouts can block threads indefinitely.
  • Ignoring idempotency — payment APIs must safely handle retries.
  • No observability — without logs, metrics and traces, production debugging is extremely difficult.

#Enterprise Architecture

Internet
Load balancer
Spring Cloud Gateway — authentication / JWT
Eureka server
User · Order · Payment · Inventory · Notification microservices
User DB · Order DB · Payment DB · Inventory DB · Kafka
Prometheus · Grafana · OpenTelemetry

#Interview Questions

Q1What is a microservice?

A small, independently deployable service that owns a specific business capability and communicates with other services over well-defined APIs or messaging.

Q2Monolith vs microservices?
MonolithMicroservices
Single deploymentIndependent deployments
Shared codebaseSeparate services
Easier initiallyBetter scalability and team autonomy
Q3What is service discovery?

A mechanism that lets services locate each other dynamically without hard-coded addresses.

Q4What is Eureka?

A service registry where microservices register themselves and discover other services.

Q5Why use an API gateway?

To provide a single entry point for routing, authentication, rate limiting, logging and other cross-cutting concerns.

Q6What is OpenFeign?

A declarative HTTP client that lets you call REST services through Java interfaces.

Q7What is a circuit breaker?

A resilience pattern that temporarily stops calls to a failing service to prevent cascading failures.

Q8What is the Saga pattern?

A distributed-transaction pattern where each service performs a local transaction and, if necessary, executes compensating actions instead of relying on a global transaction.

Q9What is idempotency?

The property that lets the same request be safely retried multiple times while producing the effect only once.

Q10Why should each microservice have its own database?

To maintain loose coupling, independent deployments and clear ownership of data.

#Key Takeaways

  • Microservices split a large application into independently deployable services.
  • Each service owns its database and exposes APIs instead of sharing data.
  • API gateways centralize routing, authentication and cross-cutting concerns.
  • Service discovery removes hard-coded service addresses.
  • OpenFeign simplifies service-to-service REST calls.
  • Resilience4j provides circuit breakers, retries, bulkheads and timeouts.
  • Sagas and idempotency handle distributed business processes safely.
  • Observability — metrics, logs and distributed tracing — is critical in production.