Microservices and Distributed Systems: Modules
The program teaches the core difficulties of distributed systems inside a real decision framework: where to draw service boundaries, how to decide who owns which data, and how to live with network failure. It also states openly that microservices are not always the answer and analyses the cases where a modular monolith is the better choice.
01
Service boundaries
Learning to split services by business capability rather than by technical layer.
- Bounded context and the basics of domain-driven design
- Boundary signals: change frequency and team ownership
- Kinds of coupling and the distributed-monolith trap
- Gradual decomposition with the strangler approach
- The modular monolith as an alternative
Lab: Propose a service split for a given monolithic ordering system and compare two alternatives in a trade-off table.
02
Data ownership
Answering how queries and reports work once each service owns its data.
- Database per service and the risks of a shared database
- Data duplication and read models
- API composition and an introduction to CQRS
- Living without cross-service referential integrity
- Data migration and schema ownership
Lab: Separate two services that share a table: draw the ownership boundary and write a staged plan to move the data.
03
Synchronous and asynchronous communication
Comparing the consequences of choosing REST, gRPC or messaging.
- REST versus gRPC: contract and performance differences
- Messaging and event-based interaction
- Temporal coupling and availability arithmetic
- Contract tests (consumer-driven contracts)
- The role of an API gateway and a BFF
Lab: Build the same workflow synchronously and asynchronously and compare availability and latency.
04
Failure handling
The network is unreliable; we design the system to respond to that properly.
- Timeout budgets and cascading failure
- Retries, exponential backoff and jitter
- Circuit breakers, bulkheads and load shedding
- Idempotency keys
- An introduction to chaos experiments
Lab: Inject faults into a service and compare system behaviour with and without timeouts and a circuit breaker.
05
Sagas and consistency models
Working with compensating flows and eventual consistency instead of distributed transactions.
- Strong versus eventual consistency
- Sagas: choreography and orchestration
- Compensating actions and steps that cannot be undone
- Transactional outbox
- Showing partial state to the user
Lab: Build a saga across order, payment and warehouse services and verify compensation on payment failure with tests.
06
Distributed tracing and observability
Making visible what happens when one request crosses several services.
- Traces, spans and context propagation
- Instrumentation with OpenTelemetry
- Correlation IDs across services
- Service maps and dependency analysis
- SLO-based alerting
Lab: Set up OpenTelemetry across a three-service flow and locate the source of a slowdown from the trace.
07
Deployment: containers and Kubernetes concepts
The concepts needed to package and run a service, without going into cluster administration.
- Docker image layers and small images
- Deployment, Service and ConfigMap concepts
- Liveness and readiness probes
- Resource requests/limits and JVM memory alignment
- Rolling updates and rollback
Lab: Containerise a service, write a deployment manifest and observe the consequences of misconfigured probes.
08
When a modular monolith is better
An honest assessment of the real cost of choosing microservices, and of the alternatives.
- The cost of operational complexity
- Team size and Conway's law
- Boundary discipline inside a modular monolith
- Writing a decision record (ADR)
Lab: For a given company scenario, compare monolith, modular monolith and microservices in ADR format and write the decision.