Microservices
Service decomposition, inter-service communication, and resilience patterns.
Decomposing by data ownership, not by feature
The decomposition boundary that holds up over time is data ownership: a service owns a bounded set of tables and is the only thing allowed to write to them. Decomposing by feature team instead of data ownership tends to produce services that all reach into each other's databases within a year, which is a monolith wearing a service mesh.
Synchronous vs. event-driven communication
Use synchronous request/response (REST or gRPC) for anything the caller needs to react to immediately โ an authorization check, a price lookup. Use events (a message broker like Kafka or SQS) for anything that represents 'this happened' rather than 'answer me now' โ order placed, user updated. Mixing the two deliberately, rather than defaulting to one everywhere, is what keeps a service graph debuggable.
Resilience patterns worth the complexity
Circuit breakers and timeouts on every outbound call, idempotency keys on every write endpoint that might be retried, and a dead-letter queue for events that fail processing repeatedly. These four patterns catch the large majority of cascading-failure incidents we see in service-to-service architectures.
- Timeouts + circuit breakers on all outbound calls
- Idempotency keys on retryable writes
- Dead-letter queues for poison messages
- Bulkheads to isolate a slow dependency from the whole request pool
Working through something like this?
Get a scored blueprint in the Architecture Lab, or talk it through with the Architect Assistant first.