Episode 6 — Scaling Reliability Microservices Web3 / 6.1 — Microservice Foundations
6.1 -- Quick Revision
A compact, print-friendly cheat sheet covering all five subtopics of Microservice Foundations. Designed for last-minute review before interviews or exams.
Navigation README | Exercise Questions | Interview Questions | Quick Revision
How to Use This Material
- Print it or keep it open on a second screen.
- Cover the right column of each table and test yourself.
- Review code snippets -- they are the minimum you should be able to write from memory.
- Read through once the night before, then once more in the morning.
1. Vocabulary Table
| Term | Definition |
|---|---|
| Monolith | Single codebase, single deployment, shared database |
| Microservice | Independently deployable service owning one business capability and its data |
| Distributed monolith | Separately deployed services that are still tightly coupled (shared DB, always deploy together) |
| Modular monolith | Single deployment with strict internal module boundaries |
| Bounded context | Boundary within which a domain model is defined and consistent (DDD) |
| Ubiquitous language | Shared vocabulary between devs and domain experts within a bounded context |
| Aggregate | Cluster of objects treated as a single unit for data changes |
| Entity | Object with unique identity that persists over time (e.g., User) |
| Value Object | Object defined by its attributes, not identity (e.g., Money, Address) |
| Domain Event | Record of something meaningful that happened (e.g., OrderPlaced) |
| Saga | Sequence of local transactions with compensating actions on failure |
| Eventual consistency | Data converges across services over time, not immediately |
| CQRS | Command Query Responsibility Segregation -- separate read and write models |
| API Composition | Aggregating data from multiple services via their APIs |
| Circuit breaker | Pattern that stops calling a failing service and returns a fallback |
| Idempotency | Processing the same message N times produces the same result |
| Anti-Corruption Layer | Translation layer between an external model and your internal model |
| Strangler Fig Pattern | Incremental migration from monolith to microservices |
| Temporal coupling | Both services must be running at the same time for communication to work |
| Compensating transaction | An action that undoes a previous step in a saga |
2. Monolith vs Microservices Comparison
| Dimension | Monolith | Microservices |
|---|---|---|
| Deployment | Single artifact | Many independent artifacts |
| Database | Shared (one DB) | Database per service |
| Scaling | Scale everything | Scale individual services |
| Transactions | ACID (easy) | Eventual consistency (sagas) |
| Inter-module calls | In-process (ns) | Network (ms, can fail) |
| Team coupling | High (shared code) | Low (independent repos) |
| Technology | One stack | Polyglot possible |
| Debugging | Simple stack traces | Distributed tracing needed |
| Deployment risk | High (all-or-nothing) | Low (isolated blast radius) |
| Operational cost | Low | High (N pipelines, N dashboards) |
| Best for | Small teams, early products | Large teams, complex domains |
3. Decision Framework
Should you use microservices? Score each factor 1-5:
| Factor | 1-2 (Monolith) | 3 (Modular Monolith) | 4-5 (Microservices) |
|---|---|---|---|
| Team size | < 8 | 8-20 | > 20 |
| Deploy frequency | Weekly | Daily | Multiple/day |
| Domain complexity | 1-2 domains | 3 domains | 4+ domains |
| Scaling variance | Uniform | Some hot spots | Highly variable |
| Uptime requirement | 99% | 99.9% | 99.99% |
| Tech diversity | One stack | Minor | Multiple stacks needed |
| Regulatory isolation | None | Some | Required |
- 7-14: Monolith
- 15-21: Modular monolith
- 22-35: Microservices
Red flags for premature microservices:
- Team < 5 engineers
- "We might need to scale"
- No CI/CD or monitoring infrastructure
- Single, simple domain
- Early-stage startup still finding product-market fit
4. DDD Basics for Service Boundaries
Domain --> Subdomains --> Bounded Contexts --> Services
E-commerce domain:
Catalog (products, search, reviews)
Ordering (cart, orders, order items)
Payment (charges, refunds, invoices)
Shipping (shipments, tracking, labels)
Identity (users, auth, profiles)
Notification (email, SMS, push)
Boundary Heuristics:
- Can it deploy independently?
- Can one team (2-8 people) own it?
- Does it map to a business capability (not a tech layer)?
- Is coupling to other services low?
- Does the data change together (high cohesion)?
Common Mistakes:
- Splitting by CRUD operation (CreateUser, ReadUser, etc.)
- Splitting by technical layer (Frontend Service, DB Service)
- Sharing databases across services
- Nano-services that always deploy together
5. Database Patterns
Database per Service
+--------+ +--------+ +---------+
| Svc A | | Svc B | | Svc C |
+---+----+ +---+----+ +----+----+
| | |
+---+----+ +---+----+ +----+----+
| DB A | | DB B | | DB C |
+--------+ +--------+ +---------+
Rule: Services access ONLY their own DB. Cross-service = API or events.
Saga Pattern
Choreography (events, decentralised):
OrderCreated -> InventoryReserved -> PaymentSucceeded -> OrderConfirmed
If payment fails: PaymentFailed -> InventoryReleased -> OrderCancelled
Orchestration (central coordinator):
Orchestrator --> reserve inventory --> charge payment --> confirm order
On failure: --> refund payment --> release inventory --> cancel order
Use choreography for 2-4 steps. Use orchestration for 5+ steps.
API Composition
// Aggregate data from multiple services
const [user, orders, reviews] = await Promise.all([
axios.get(`${USER_SVC}/users/${id}`),
axios.get(`${ORDER_SVC}/orders?userId=${id}`),
axios.get(`${REVIEW_SVC}/reviews?userId=${id}`),
]);
res.json({ user: user.data, orders: orders.data, reviews: reviews.data });
CQRS
Writes --> Normalised DB (Postgres)
|
Events (OrderCreated, OrderUpdated)
|
Reads --> Denormalised DB (Elasticsearch, Mongo)
Use when read/write patterns differ significantly, complex queries needed, or high read-to-write ratio.
6. Communication Patterns
Quick Reference
| Pattern | Type | Use When |
|---|---|---|
| REST (HTTP/JSON) | Sync | External APIs, simple service calls |
| gRPC (HTTP/2 + Protobuf) | Sync | High-throughput internal calls, streaming |
| Message Queue (RabbitMQ) | Async | Task distribution, one consumer per message |
| Pub/Sub (RabbitMQ/Kafka) | Async | Event notification, many consumers per event |
| Kafka | Async | High-throughput event streaming, replay needed |
Decision Tree
Caller needs result NOW?
YES --> Sync (REST or gRPC)
Internal + high throughput? --> gRPC
External or simple? --> REST
NO --> Async
One consumer? --> Message queue
Many consumers? --> Pub/sub
REST Resilience Essentials
// 1. Timeout (ALWAYS)
axios.get(url, { timeout: 3000 });
// 2. Retry with backoff
axiosRetry(client, {
retries: 3,
retryDelay: (n) => Math.pow(2, n) * 1000 // 1s, 2s, 4s
});
// 3. Circuit breaker
const breaker = new CircuitBreaker(fn, {
errorThresholdPercentage: 50,
resetTimeout: 10000,
});
breaker.fallback(() => cachedData);
Event Publishing (RabbitMQ)
// Publish
channel.publish('domain-events', 'order.created',
Buffer.from(JSON.stringify(eventData)),
{ persistent: true }
);
// Subscribe
channel.consume(queue, async (msg) => {
const event = JSON.parse(msg.content.toString());
await processEvent(event);
channel.ack(msg);
});
Idempotency Pattern
// Check idempotency key before processing
const existing = await db.query(
'SELECT id FROM processed_events WHERE event_id = $1',
[event.eventId]
);
if (existing.rows.length > 0) return; // already processed
// Process + record in same transaction
await db.query('BEGIN');
await processPayment(event);
await db.query('INSERT INTO processed_events (event_id) VALUES ($1)', [event.eventId]);
await db.query('COMMIT');
7. RabbitMQ vs Kafka
| RabbitMQ | Kafka | |
|---|---|---|
| Model | Message queue | Distributed log |
| Delivery | Push to consumers | Consumers pull |
| Retention | Deleted after ack | Retained (configurable) |
| Replay | No | Yes |
| Throughput | Thousands/sec | Millions/sec |
| Best for | Task queues, routing | Event streaming, replay |
8. Common Gotchas
| Gotcha | Why It Hurts | Fix |
|---|---|---|
| Shared database | Hidden coupling, breaks independence | Database per service |
| No timeouts on HTTP calls | One slow service brings down the chain | Set 2-3s timeouts on every call |
| No circuit breaker | Cascading failures | Use opossum or similar library |
| Not idempotent consumers | Double-processing on retry | Idempotency key in every event |
| Synchronous everything | Temporal coupling, latency chains | Use async where caller does not need immediate result |
| Splitting too thin | Nano-services with high coupling | Merge services that always change/deploy together |
| Splitting by tech layer | Distributed monolith | Split by business capability |
| Big bang migration | High risk, long timeline | Strangler Fig (incremental) |
| No distributed tracing | Cannot debug cross-service issues | Correlation IDs + Jaeger/Datadog |
| Ignoring eventual consistency | UX surprises (order not showing immediately) | Read-your-writes, optimistic UI |
9. Architecture Diagram (Reference)
+------------------+
| API Gateway / |
| Load Balancer |
+--------+---------+
|
+----------------+----------------+
| | |
+------+------+ +-----+-------+ +------+------+
| User | | Order | | Catalog |
| Service | | Service | | Service |
+------+------+ +-----+-------+ +------+------+
| | |
+------+------+ +-----+-------+ +------+------+
| Users DB | | Orders DB | | Catalog DB |
| (Postgres) | | (Postgres) | | (Postgres) |
+-------------+ +-------------+ +-------------+
| | |
+--------+-------+--------+-------+
| |
+------+------+ +------+------+
| Message | | Notification|
| Broker | | Service |
| (RabbitMQ) | +------+------+
+-------------+ |
+-----+------+
| Payment |
| Service |
+-----+------+
|
+-----+------+
| Payment DB |
| (Postgres) |
+------------+
10. Key Numbers to Remember
| Metric | Guideline |
|---|---|
| Team size for microservices | 15+ engineers |
| Timeout for service calls | 2-3 seconds |
| Circuit breaker error threshold | 50% |
| Circuit breaker reset timeout | 10-30 seconds |
| Retry attempts | 3 with exponential backoff |
| Retry delays | 1s, 2s, 4s (powers of 2) |
| Choreography saga steps | 2-4 (max) |
| Orchestration saga steps | 5+ |
| Bounded context to service ratio | 1:1 |
| Team size per service | 2-8 (two-pizza team) |
11. One-Sentence Summaries
| Topic | One Sentence |
|---|---|
| 6.1.a | A monolith is simpler but microservices offer independent deployment and scaling -- start monolith, evolve when needed. |
| 6.1.b | Microservices are a trade-off (not an upgrade) justified by large teams, high deploy frequency, and complex domains. |
| 6.1.c | Draw service boundaries along bounded contexts using DDD -- split by business capability, not by technical layer. |
| 6.1.d | Each service owns its database; use sagas for distributed transactions and CQRS for complex read patterns. |
| 6.1.e | Use sync (REST/gRPC) when you need immediate results, async (queues/events) when you can defer processing. |
Print this page. Review it. Ace the interview.
Navigation README | Exercise Questions | Interview Questions | Quick Revision