Service Core · companion to Java Core, Spring Core & Unix Core

Microservices architecture without the hype

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.

What are microservices? The Netflix origin story

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.

Monolith vs microservices — honest comparison

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
⚖️ Trade-off

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.

🎯 Interview Tip

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.”

The 8 fallacies of distributed computing

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.

  1. Fallacy 1

    The network is reliable

    Packets drop, DNS fails, TLS handshakes stall. Design timeouts, retries with backoff, and idempotent handlers.

  2. Fallacy 2

    Latency is zero

    Every hop adds milliseconds—and tail latency multiplies across chains. Prefer aggregation, caching, and async where possible.

  3. Fallacy 3

    Bandwidth is infinite

    Chatty fine-grained APIs saturate links and budgets. Batch, paginate, and push only what consumers need.

  4. Fallacy 4

    The network is secure

    Assume breach: mTLS between services, least-privilege tokens, secrets in Vault—not env files in git.

  5. Fallacy 5

    Topology doesn’t change

    Pods reschedule, regions fail, services scale. Use discovery (K8s DNS, Eureka) not hardcoded hosts.

  6. Fallacy 6

    There is one administrator

    Many teams deploy independently—coordinate via contracts, versioning, and consumer-driven tests (Pact).

  7. Fallacy 7

    Transport cost is zero

    Serialization, TLS, and gateway hops cost CPU and money. gRPC and binary formats help at high volume.

  8. Fallacy 8

    The network is homogeneous

    Mixed runtimes, clouds, and legacy SOAP/XML neighbors exist. Anti-corruption layers and gateways bridge worlds.

⚠️ Pitfall

Treating remote calls like local method invocations (@FeignClient without timeouts) recreates fallacies 1–3 in production outages.

Microservices principles

These principles guide decomposition and operations—not a checklist to micro-split every class.

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

When NOT to use microservices

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.

🚫 Anti-Pattern

Microservices because the architect read a book — splitting by technical layer (Controller Service, Database Service) creates chatty coupling without business autonomy.

💡 Pro Tip

Extract the first service where pain is undeniable: different scaling profile, different release cadence, or regulatory isolation—not because the diagram looks cleaner.

Architecture evolution path

Mature organizations rarely jump straight to microservices. This path reduces risk and preserves delivery velocity.

  1. Stage 1

    Monolith

    Single deployable. Optimize for speed of learning and transactional integrity.

  2. Stage 2

    Modular monolith

    Clear modules / packages per bounded context. Enforce boundaries with ArchUnit-style tests.

  3. Stage 3

    Strangler fig

    Route traffic to new services behind a gateway; peel off capabilities incrementally.

  4. Stage 4

    Microservices

    Independent data, CI/CD per service, platform team for K8s, observability, and paved roads.

📦 Real World

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.

Technology landscape map

Service Core teaches patterns first; these tools are how Java/Spring teams typically implement them in production.

Spring & JVM platform

  • Spring Cloud — config, discovery, gateway, stream binders
  • Spring Cloud Gateway — reactive routing, filters, rate limiting
  • Resilience4j — circuit breaker, retry, bulkhead, rate limiter

Runtime & mesh

  • Kubernetes — orchestration, service DNS, HPA, probes
  • Istio / Linkerd — mTLS, traffic shifting, telemetry
  • Consul — service discovery and health (non-K8s estates)

Data & messaging

  • Apache Kafka — event backbone, log compaction, outbox relay
  • PostgreSQL / Redis / Elasticsearch — polyglot persistence per service

Security & secrets

  • HashiCorp Vault — dynamic secrets, Spring Cloud Vault
  • OAuth2 / JWT — gateway validation, token relay downstream

Observability

  • OpenTelemetry → Jaeger — distributed tracing
  • Prometheus + Grafana — RED metrics, SLO dashboards

Delivery

  • ArgoCD / Flux — GitOps declarative deploys
  • Helm — templated K8s manifests per environment
🔬 Under the Hood

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).

Explore the guide — all sections

Ten deep-dive chapters plus patterns catalog and cheat sheets. Recommended path: Service DesignCommunicationResilienceData Patterns, then platform topics as your role requires.

Learning path: Service Design · Communication · Resilience · Data Patterns · Observability

Developer

developer

REST/gRPC APIs, Spring Cloud clients, Kafka consumers, Resilience4j tuning.

Tech Lead

lead

Boundaries, sync vs async, saga vs 2PC, contract testing, team topology.

Architect

architect

Mesh vs library resilience, CAP/PACELC, zero trust, GitOps, system design interviews.