Level: Beginner to Intermediate
Table of Contents
- Module 1 — What Are Microservices?
- Module 2 — Why Microservices?
- Module 3 — Communication Patterns
- Module 4 — Adopting Microservices
- Architecture Diagrams
- Reference Tables
Module 1 — What Are Microservices?
Microservices vs Monoliths
When developing software, it starts small — a few features. But as features are added, complexity accumulates. When all this complexity stays in the same program, it’s called a monolithic architecture — a monolith.
A monolith is not necessarily bad. A well-maintained monolith often has a modular architecture with abstractions that facilitate maintainability. But everything lives in the same application.
Microservices work differently: it’s a collection of independent programs that collaborate to solve business problems, rather than having all business logic in the same program.
graph TB
subgraph Monolith["Monolithic Architecture"]
M[Single Application]
M --> F1[Feature: Users]
M --> F2[Feature: Orders]
M --> F3[Feature: Payments]
M --> F4[Feature: Notifications]
M --> F5[Feature: Analytics]
end
subgraph Micro["Microservices Architecture"]
GW[API Gateway]
GW --> S1[Users Service]
GW --> S2[Orders Service]
GW --> S3[Payments Service]
GW --> S4[Notifications Service]
GW --> S5[Analytics Service]
S1 --- DB1[(Users DB)]
S2 --- DB2[(Orders DB)]
S3 --- DB3[(Payments DB)]
end
Microservices Characteristics
1. Collection of Small, Independent Services
The “micro” in microservices means small. Each service should be relatively simple to understand in its entirety, which simplifies maintenance and promotes flexibility.
2. Heterogeneous Technology Stacks
It is common for different services to use different programming languages, frameworks, and data storage technologies. This allows selecting best-of-breed solutions, experimenting with new technologies, and making stack changes with little friction.
3. Independent Development and Deployment
Each service can be redeployed without affecting others. In monolithic architectures, deployment is often all-or-nothing. This independence allows separate teams to deliver business value autonomously, without waiting for synchronization with other teams.
4. Communication Over the Network
Microservices communicate with each other via the network. Network latency is much greater than API calls within the same process — a structural constraint that reinforces separation of concerns and cohesion:
- Tightly coupled elements should be in the same microservice
- Loosely coupled elements can be in separate microservices
5. Domain-Driven Design (DDD)
The most effective approach to delimiting microservice boundaries involves applying Domain-Driven Design principles, based on:
- Bounded Context — contextual boundary of a business domain
- Ubiquitous Language — vocabulary shared between developers and business experts
The Microservices Ecosystem
Infrastructure and Containerization
| Technology | Category | Examples |
|---|---|---|
| Containerization | Runtime | Docker, Podman |
| Container Orchestration | Platform | Kubernetes, Helm |
| Cloud-Managed Containers | Cloud | AWS Elastic Beanstalk, GCP Cloud Run, Azure Container Apps |
| Event Brokers | Messaging | Apache Kafka, RabbitMQ, AWS SQS/SNS, GCP Pub/Sub, Azure Service Bus |
| Serverless Functions | Compute | AWS Lambda, GCP Cloud Run Functions, Azure Functions |
Organization and DevOps Practices
Microservices teams rely heavily on:
- Test Automation and Continuous Integration (CI)
- Continuous Deployment/Delivery (CD)
- Infrastructure as Code (IaC)
- DevOps practices: cross-functional teams, fast feedback, experimentation
- Site Reliability Engineering (SRE)
Module 2 — Why Microservices?
Microservices benefits fall into three main categories: Complexity, Scale, and Governance.
Throughout the course, these concepts are illustrated by Globomantics, a fictional social networking company with millions of global users.
Managing Complexity
Globomantics manages many distinct business complexities:
- Feed algorithm — Graph analysis to determine what content to show which user
- Content moderation — Hybrid moderation (community + ML) to detect harmful content
- Ad targeting — Machine learning to build an advertising profile per user
- Advertiser portal — Distinct interface for advertisers
With a monolithic architecture, all these complexities coexist in the same codebase, creating:
- Entanglement between unrelated domains
- Difficulty deploying isolated changes
- Risk that a bug in one feature impacts the entire system
With microservices, each complexity domain can be isolated in its own service, with its own team, deployment cycle, and adapted technology stack.
Microservices and Scale
Scale Challenges at Globomantics
| Metric | Estimate |
|---|---|
| Total users | 1,000,000 |
| Simultaneous active users (5%) | 50,000 |
| Requests/sec (0.1 req/user/sec) | 5,000 req/s |
| Load spikes | Up to 100,000+ req/s |
Types of Workloads to Scale Differently
- Feed generation — Compute-intensive, requires lots of CPU and RAM
- Image/Video processing — Storage, content scanning, global serving with access rules
- Notifications — Very high volume of push messages
- ML ad profiles — Continuous profile updates by ML models
The key advantage: with microservices, you can scale each service independently according to its specific needs, rather than scaling the entire monolithic application.
graph LR
Users[Users] --> LB[Load Balancer]
LB --> FeedSvc[Feed Service\nx10 instances]
LB --> ImgSvc[Image Service\nx5 instances]
LB --> NotifSvc[Notification Service\nx20 instances]
LB --> AdSvc[Ad Profile Service\nx3 instances]
style FeedSvc fill:#4CAF50,color:#fff
style NotifSvc fill:#2196F3,color:#fff
style ImgSvc fill:#FF9800,color:#fff
style AdSvc fill:#9C27B0,color:#fff
Governance
Governance refers to the rules, structures, and processes controlling how teams work. It’s one of the most powerful benefits of microservices.
Value Streams
Each Globomantics domain represents a value stream — a distinct value contribution:
| Value Stream | Business Value |
|---|---|
| Fast, smooth feed | More ad exposure → more revenue |
| Precise ad targeting | Higher rates charged to advertisers |
| Effective content moderation | Reduced legal risk, user retention |
| Real-time notifications | User engagement and retention |
Conway’s Law
“Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.” — Melvin Conway
Microservices allow aligning organizational structure with software architecture: each team is responsible for one or more services corresponding to a business bounded context.
Module 3 — Communication Patterns
Distributed Systems and Latency
A microservices architecture is by definition a distributed system — a system composed of distinct nodes separated by a network.
Network Latency
| Context | Typical Latency |
|---|---|
| Local RAM access | ~1–10 nanoseconds |
| Same Kubernetes cluster / same cloud region | ~1–5 milliseconds |
| Multi-region | ~10–100+ milliseconds |
Network latency is hundreds of thousands to millions of times slower than local memory access. Every network hop accumulates.
Availability
Availability is measured as a percentage of successful responses:
| Availability | Downtime / year |
|---|---|
| 99% | ~3.65 days |
| 99.9% | ~8.7 hours |
| 99.99% | ~52 minutes |
| 99.999% | ~5 minutes |
The cascading dependencies problem:
If Service A depends on B, C, and D, each with 99.9% availability:
$$\text{Availability}_A = 0.999 \times 0.999 \times 0.999 \approx 99.7%$$
Overall availability degrades with every added synchronous dependency.
RPC Communications
Remote Procedure Call (RPC) is the simplest form of communication between microservices: a client sends a request to a server and waits for its response.
Common examples:
- REST endpoints (HTTP/JSON)
- gRPC (Google’s framework — Protocol Buffers, HTTP/2)
- GraphQL
When to Use RPC?
| Condition | Recommendation |
|---|---|
| High server availability | ✅ RPC suitable |
| Low or tolerable latency | ✅ RPC suitable |
| Simple and stable dependencies | ✅ RPC suitable |
| Low server availability | ❌ Prefer async |
| Complex and numerous dependencies | ❌ Prefer messaging |
| Long operations (e.g., report generation) | ❌ Prefer async |
sequenceDiagram
participant C as Client Service
participant S as Server Service
C->>S: HTTP POST /api/resource (Request)
S-->>C: HTTP 200 OK (Response)
Note over C,S: Synchronous communication — client waits
Service Discovery and Service Meshes
In microservices, a service must know the IP address of another service to communicate with it — this is the Service Discovery problem.
Service Discovery Approaches
| Approach | Description | Limitations |
|---|---|---|
| DNS-based | Name to IP resolution (built into Kubernetes) | Insufficient for complex scenarios |
| Client-side discovery | Client consults a registry (e.g., Eureka) | Discovery logic in each client |
| Server-side discovery | A load balancer does the resolution | Potential single point of failure |
| Service Mesh | Transparent sidecar proxy (e.g., Istio) | Increased operational complexity |
Service Meshes
Service meshes (Istio, Consul, OpenShift, Rancher) go beyond simple discovery:
- Dynamic load shifting — Dynamic traffic redistribution
- Failover — Automatic failover on failure
- A/B Testing / Canary Releases — Traffic routing to different versions
- mTLS Security — Service-to-service encryption and authentication
- Observability — Metrics, traces, logs automatically enriched
Important trade-off: A service mesh adds operational complexity. Only adopt a service mesh if you have clear, current needs that justify it.
Message-driven Communication
Message-driven communication uses a message broker as an intermediary between producers and consumers. Also known as:
- Event-driven architecture
- Message-oriented architecture
- Publish/Subscribe (pub/sub)
RPC vs Message-driven Comparison
sequenceDiagram
participant P as Producer Service
participant B as Message Broker
participant C1 as Consumer 1
participant C2 as Consumer 2
P->>B: publish(PhotoUploadedEvent)
Note over P,B: Fire and forget — no waiting for response
B-->>C1: deliver(PhotoUploadedEvent)
B-->>C2: deliver(PhotoUploadedEvent)
C1->>B: publish(NotificationSentEvent)
C2->>B: publish(ContentScanCompleteEvent)
Message-driven Advantages
- Elimination of cascade failures — Broker absorbs load spikes and temporary outages
- Loose coupling — A service publishes without knowing who consumes
- Spike absorption — Broker acts as a buffer (queue)
- Observability — Queue depth is a very useful operational metric
Example: Photo Upload at Globomantics
flowchart TD
User([User]) --> API[API Service]
API --> |"publish(PhotoUploaded)"| Broker[(Message Broker\nKafka/RabbitMQ)]
Broker --> ContentScan[Content Moderation Service]
Broker --> NotifSvc[Notification Service]
Broker --> AdProfile[Ad Profile Service]
Broker --> Storage[Storage Service]
ContentScan --> |"publish(ContentScanResult)"| Broker
Storage --> |"publish(StorageComplete)"| Broker
Service Dependencies and Coupling
Coupling between services is understood through their dependencies. A Service A that depends on the APIs of Services B and C is coupled to them.
The Breaking Changes Problem
When Service B needs to publish an incompatible change (breaking change), it cannot deploy without coordinating with Service A — which breaks independence.
Solution: API Versioning
graph LR
A[Service A] --> |"GET /api/v1/users"| B_v1[Service B\nAPI v1 — deprecated]
A2[Service A\nupdated] --> |"GET /api/v2/users"| B_v2[Service B\nAPI v2 — current]
B_v1 -.->|"evolves to"| B_v2
Versioning strategy:
- Service B publishes the breaking change in a new version
/api/v2/ - The old version
/api/v1/remains available but deprecated - Consumers receive deprecation warnings
- Service A prioritizes migration to
/api/v2/ - Once all consumers migrated,
/api/v1/is removed
Module 4 — Adopting Microservices
DORA Metrics — Assessing Capabilities
Before adopting microservices, assess whether the organization has the necessary capabilities. Microservices are much more complex to build and operate than a monolithic architecture.
The DevOps Research and Assessment (DORA) program defines 4 key metrics:
| DORA Metric | Description | Elite Target |
|---|---|---|
| Deployment Frequency | Frequency of production deployments | Multiple times per day |
| Lead Time for Changes | Time from commit to production | Less than one day |
| Change Failure Rate | % of deployments requiring immediate remediation | 0–15% |
| Mean Time to Recovery (MTTR) | Average time to restore service after incident | Less than one hour |
Organizational Prerequisites
- Automated and reliable CI/CD pipelines
- Complete test automation (unit, integration, end-to-end)
- Infrastructure as Code for reproducible deployments
- Robust monitoring and alerting
- Culture of blameless post-mortems and continuous improvement
Common Pitfalls
Gall’s Law
“A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.” — John Gall
Common Pitfalls to Avoid
| Pitfall | Description | Recommendation |
|---|---|---|
| Too big, too fast | Moving from monolith to dozens of microservices at once | Migrate progressively, service by service |
| Over-engineering messaging | Adopting an event broker without mastering async patterns | Start with simple RPC, add messaging as needed |
| Unfamiliar data storage | Using a new DB technology for each service | Master known technologies first |
| Premature service mesh | Adopting Istio/Consul without a clear need | Use DNS-based discovery until you need more |
| Distributed monolith | Tightly coupled services that deploy together | Review bounded contexts, reduce coupling |
| Neglecting observability | No centralized logs, no distributed tracing | Implement logging, metrics, tracing from the start |
| Ignoring DORA metrics | Not measuring delivery capabilities | Track the 4 DORA metrics regularly |
The Strangler Fig Pattern
For progressively migrating from a monolith to microservices:
flowchart LR
Client([Client]) --> Proxy[Proxy / API Gateway]
Proxy --> |"New functionality"| NewSvc[New Microservice]
Proxy --> |"Old functionality"| Monolith[Existing Monolith]
style NewSvc fill:#4CAF50,color:#fff
style Monolith fill:#FF5722,color:#fff
Progressively, the monolith shrinks and microservices grow.
Further Resources
| Book | Author(s) | Theme |
|---|---|---|
| The Software Architect Elevator | Gregor Hohpe | Technical leadership, communication, architect coaching |
| Microservices Patterns | Chris Richardson | Tactical patterns with diagrams and code samples |
| Site Reliability Engineering | Beyer, Jones, Petoff, Murphy | Operating complex systems, SRE at Google |
Architecture Diagrams
API Gateway Pattern
graph TD
WebApp([Web App]) --> GW[API Gateway]
MobileApp([Mobile App]) --> GW
ThirdParty([Third-party Client]) --> GW
GW --> |"Auth check"| AuthSvc[Auth Service]
GW --> |"/api/users/*"| UserSvc[User Service]
GW --> |"/api/orders/*"| OrderSvc[Order Service]
GW --> |"/api/products/*"| ProductSvc[Product Service]
GW --> |"/api/payments/*"| PaySvc[Payment Service]
UserSvc --- UserDB[(Users DB)]
OrderSvc --- OrderDB[(Orders DB)]
ProductSvc --- ProductDB[(Products DB)]
PaySvc --- PayDB[(Payments DB)]
style GW fill:#FF9800,color:#fff
style AuthSvc fill:#F44336,color:#fff
Circuit Breaker Pattern
stateDiagram-v2
[*] --> Closed: Initial state
Closed --> Open: Failure threshold reached\n(e.g.: 5 failures in 10s)
Open --> HalfOpen: After timeout\n(e.g.: 30 seconds)
HalfOpen --> Closed: Test request succeeds
HalfOpen --> Open: Test request fails
note right of Closed
All requests pass through
Errors are counted
end note
note right of Open
All requests fail immediately
No call to degraded service
(Fast fail)
end note
note right of HalfOpen
One test request passes
to verify recovery
end note
Saga Pattern (Choreography-based)
sequenceDiagram
participant OS as Order Service
participant PS as Payment Service
participant IS as Inventory Service
participant NS as Notification Service
OS->>+PS: OrderCreated event
PS-->>-OS: PaymentProcessed event
OS->>+IS: ReserveInventory event
IS-->>-OS: InventoryReserved event
OS->>NS: OrderConfirmed event
NS-->>OS: NotificationSent event
Note over OS,NS: Each service reacts to events\nNo central coordinator
rect rgb(255, 200, 200)
OS->>PS: (on failure) OrderCancelled event
PS-->>OS: PaymentRefunded event
Note over OS,PS: Compensating transactions on failure
end
Reference Tables
Microservices Patterns
| Pattern | Purpose | When to Use |
|---|---|---|
| API Gateway | Single entry point for clients | Multiple clients, cross-cutting concerns |
| Circuit Breaker | Prevent cascade failures | Services with availability issues |
| Saga | Distributed transactions | Multi-service business operations |
| Strangler Fig | Progressive migration from monolith | Legacy modernization |
| Sidecar | Inject infrastructure features | Logging, monitoring, service mesh |
| Event Sourcing | Store state as events | Audit trail, temporal queries |
| CQRS | Separate read and write models | High performance reads + writes |
Communication Comparison
| Aspect | RPC (Synchronous) | Message-driven (Async) |
|---|---|---|
| Coupling | Tight | Loose |
| Availability dependency | Yes | No |
| Response time | Immediate | Deferred |
| Complexity | Low | Medium to high |
| Use cases | Simple queries | Complex workflows |
| Resilience | Lower | Higher |
| Observability | Direct | Queue depth as indicator |
DORA Metrics Reference
| Metric | Low Performer | Medium | High | Elite |
|---|---|---|---|---|
| Deployment Frequency | < 1/month | 1/month–1/week | 1/week–1/day | Multiple/day |
| Lead Time | > 6 months | 1 month–6 months | 1 week–1 month | < 1 day |
| MTTR | > 1 week | 1 day–1 week | < 1 day | < 1 hour |
| Change Failure Rate | 46–60% | 16–45% | 16–30% | 0–15% |
mindmap
root((Microservices))
Architecture
Bounded Context
Domain-Driven Design
Independent Services
Communication
RPC
REST
gRPC
GraphQL
Async
Pub/Sub
Event-driven
Message Broker
Service Discovery
DNS
Service Mesh
Patterns
API Gateway
Circuit Breaker
Saga
Event Sourcing
CQRS
Strangler Fig
Benefits
Complexity Management
Independent Scaling
Team Autonomy
Technology Freedom
Prerequisites
CI/CD Pipelines
Test Automation
IaC
DORA Metrics
DevOps Culture
Ecosystem
Docker
Kubernetes
Kafka
Istio
Cloud Providers
Note: Microservices are among the most complex systems ever built. Organizations like Google, Netflix, Spotify, and Amazon use this approach at very large scale. Independence — of both services AND teams — is the key to success in microservices architectures.
Search Terms
microservices · foundations · java · backend · architecture · full-stack · web · communication · pattern · service · message-driven · rpc · scale · comparison · discovery · dora · globomantics · independent · latency · law · meshes · metrics · network · patterns