Developer
developerREST/gRPC APIs, Spring Cloud clients, Kafka consumers, Resilience4j tuning.
Service Core · companion to Java Core, Spring Core & Unix Core
Learn distributed systems thinking from first principles—service boundaries, communication, data consistency, resilience, and production operations—with architecture patterns and their Java/Spring Cloud implementations side by side.
In 2008, a single corrupted database connection took down Netflix’s entire monolithic DVD rental stack for three days. That outage became the catalyst for a multi-year migration: decompose the monolith into independently deployable services, each owning its data and scaling on its own failure domain. The pattern spread—not because “micro” sounds modern, but because independent deployability and failure isolation matched their scale and pace of change.
Microservices are an organizational and architectural style: small services aligned to business capabilities, communicating over the network, with decentralized data and automated operations. They are not a framework feature—you still must design boundaries, consistency, and observability deliberately.
Microservices are not always better. A well-structured monolith often beats a poorly decomposed distributed system. Choose based on team topology, change frequency, and operational maturity—not conference slides.
| Dimension | Monolith (modular) | Microservices |
|---|---|---|
| Deploy unit | One artifact; simple rollbacks | Many services; needs CI/CD, versioning discipline |
| Consistency | ACID transactions in one database | Sagas, eventual consistency, harder reasoning |
| Latency | In-process calls (nanoseconds–µs) | Network hops (ms+); timeouts, retries, cascading failure |
| Scale | Scale entire app together | Scale hot services independently |
| Team autonomy | Shared codebase; coordination overhead | Two-pizza teams own services end-to-end |
| Operational cost | Lower baseline—one process, one DB | K8s, mesh, tracing, on-call per service |
| Failure blast radius | One bug can take down everything | Isolation—if boundaries are right |
You trade development simplicity for operational flexibility. If you cannot run containers, observe distributed traces, and manage schema migrations per service, a modular monolith is the rational default.
Interviewers want nuance: “We’d start modular monolith + clear bounded contexts, extract services when deploy cadence or scale forces it—strangler fig, not big-bang rewrite.”
Peter Deutsch and colleagues at Sun (1994) listed assumptions that bite every microservices team. Internalize these before you design APIs or pick sync vs async.
Packets drop, DNS fails, TLS handshakes stall. Design timeouts, retries with backoff, and idempotent handlers.
Every hop adds milliseconds—and tail latency multiplies across chains. Prefer aggregation, caching, and async where possible.
Chatty fine-grained APIs saturate links and budgets. Batch, paginate, and push only what consumers need.
Assume breach: mTLS between services, least-privilege tokens, secrets in Vault—not env files in git.
Pods reschedule, regions fail, services scale. Use discovery (K8s DNS, Eureka) not hardcoded hosts.
Many teams deploy independently—coordinate via contracts, versioning, and consumer-driven tests (Pact).
Serialization, TLS, and gateway hops cost CPU and money. gRPC and binary formats help at high volume.
Mixed runtimes, clouds, and legacy SOAP/XML neighbors exist. Anti-corruption layers and gateways bridge worlds.
Treating remote calls like local method invocations (@FeignClient without timeouts) recreates fallacies 1–3 in production outages.
These principles guide decomposition and operations—not a checklist to micro-split every class.
One reason to change—aligned to a business capability (billing, catalog, recommendations), not a technical layer.
Deploy without coordinating the entire system. If you always release together, you have a distributed monolith.
Database per service—no shared schema. Integrate via APIs and events, not cross-service SQL joins.
Bounded contexts from DDD map to service boundaries. Ubiquitous language crosses team and API design.
Bulkheads, circuit breakers, and graceful degradation so one dependency’s outage doesn’t sink the platform.
Metrics, structured logs, and distributed traces are not optional—debugging happens across ten services, not one stack trace.
flowchart LR Client[Mobile / Web Client] GW[API Gateway] S1[Order Service] S2[Inventory Service] S3[Payment Service] K[(Kafka)] Client --> GW GW --> S1 GW --> S2 S1 --> K S2 --> K S1 --> S3
David Heinemeier Hansson’s Majestic Monolith argument: Basecamp ships a single Rails app because team size, domain stability, and operational cost favor cohesion over distribution.
Microservices because the architect read a book — splitting by technical layer (Controller Service, Database Service) creates chatty coupling without business autonomy.
Extract the first service where pain is undeniable: different scaling profile, different release cadence, or regulatory isolation—not because the diagram looks cleaner.
Mature organizations rarely jump straight to microservices. This path reduces risk and preserves delivery velocity.
Stage 1
Single deployable. Optimize for speed of learning and transactional integrity.
Stage 2
Clear modules / packages per bounded context. Enforce boundaries with ArchUnit-style tests.
Stage 3
Route traffic to new services behind a gateway; peel off capabilities incrementally.
Stage 4
Independent data, CI/CD per service, platform team for K8s, observability, and paved roads.
Amazon moved to service-oriented architecture around 2002 (“two-pizza teams”). Uber strangler-migrated domains from a single API to hundreds of services as regions and product lines exploded.
Service Core teaches patterns first; these tools are how Java/Spring teams typically implement them in production.
A “simple” REST call traverses DNS → load balancer → sidecar Envoy → service pod → connection pool → DB. Service Core chapters map each hop to patterns (timeout, retry, trace propagation).
Ten deep-dive chapters plus patterns catalog and cheat sheets. Recommended path: Service Design → Communication → Resilience → Data Patterns, then platform topics as your role requires.
Learning path: Service Design · Communication · Resilience · Data Patterns · Observability
REST/gRPC APIs, Spring Cloud clients, Kafka consumers, Resilience4j tuning.
Boundaries, sync vs async, saga vs 2PC, contract testing, team topology.
Mesh vs library resilience, CAP/PACELC, zero trust, GitOps, system design interviews.
DDD, bounded contexts, API design, strangler fig, ACL.
Sync/async, discovery, gateway, Kafka, outbox.
Timeouts, retries, circuit breakers, bulkheads, fallbacks.
Sagas, CQRS, event sourcing, CAP, transactional outbox.
Istio traffic management, mTLS, Kiali, sidecar pattern.
Zero trust, token relay, Vault, API security top 10.
Logs, metrics, traces, OpenTelemetry, SLOs.
Containers, K8s, canary, GitOps, CI/CD pipelines.
Visual catalog + decision helper widget.
Developer, tech lead, and architect quick references.