1. What It Is
Microservices aren't a day-one choice β they're how we decompose a monolith once team boundaries and scale demand it. Strangler fig, saga, and outbox are the patterns interviewers expect you to name.
What:
Core architectural patterns designed to decouple monolithic databases and applications into independent, resilient microservices.
Primary purpose:
Enabling incremental code migrations, maintaining atomic multi-service transactions, and guaranteeing reliable system integration streams.
Usually used for:
Monolith-to-microservices migrations, distributed e-commerce transactions, and outbox event streams.
2. Core Mental Model
How should I think about this inside system architectures?
πΏ The Strangler Fig
Never execute a 'big bang' rewrite. Wrap the old monolith in an API gateway proxy, gradually strangling old features as new microservices replace them.
βοΈ Sagas & Compensations
Avoid locking distributed transactions. Run local updates instantly. On failure, fire undo actions in reverse chronological order.
π¬ Atomic Outbox Delivery
Avoid dual-write failures. Write database state updates and outbox events in a single SQL transaction, using CDC relays to publish events to Kafka.
In the room
Don't microservice everything because it sounds modern. Strangler fig for migration, saga for cross-service transactions, outbox for reliable events. Warn about distributed tracing and deployment complexity as costs.
3. Why It Matters in HLD
Microservices patterns manage migration, consistency, and delivery across service boundaries. Three lenses:
Needed When:
Migrating legacy monolithic codebases to microservices, or building reliable transactional e-commerce checkout systems.
Avoids:
Dual-write data inconsistencies, high-risk migrations outages, tight code dependencies coupling, and lost transactional events.
Optimizes For:
Software release frequencies, deployment independence, transaction consistency boundaries, and migration safeties.
4. Architecture & Data Flow
Walk three patterns as parallel paths. Strangler: proxy routes traffic; new features go to new service; old monolith shrinks. Saga: choreographed or orchestrated steps with compensations on failure. Outbox: atomic local write + outbox row; relay publishes to bus β reliable at-least-once.
Diagram A β Strangler Fig + Saga
Diagram B β Transactional Outbox (optional: service mesh for mTLS only)
The outbox diagram below is the critical path for reliable events. Service mesh sidecars (Envoy) are optional infrastructure for mTLS and observability β mention briefly, do not over-index unless the interviewer asks about zero-trust networking.
In the room
Warn against distributed monolith β separate repos that must deploy together is microservices theater. Strangler lets you prove value incrementally.
5. Key Characteristics
Strangler vs big-bang rewrite, saga choreography vs orchestration β we compare:
- Pattern overview β migration, distributed workflow, and reliable events:
| Design Pattern | Core Execution Mechanic | Primary Architectural Role |
|---|---|---|
| Strangler Fig Migration | API gateways steer requests incrementally from old monolith code to new microservices. |
|
| Saga Orchestration | Coordinates multi-step distributed transactions using compensating rollbacks. | Maintains eventual consistency across microservice databases. |
| Transactional Outbox | Saves updates and outbox events atomically inside the same local database transaction. | Guarantees reliable, at-least-once outbound event delivery. |
6. Strategic Tradeoffs
Independent deployability trades distributed complexity β we articulate both:
| Benefit | Cost |
|---|---|
| Decoupled Scaling (allows development teams to deploy and scale independent microservices services autonomously) | Operational Complexity (managing distributed transactions, network latency hops, and cluster tracing requires significant tooling) |
| Incremental Rewrite Safeties (Strangler Fig mitigates big-bang migration rewrite failures by testing routes incrementally) | Data Synchronization Lags (maintaining dual-write database syncs during modernizations adds data overhead) |
7. Failure / Bottleneck Awareness
Distributed monolith, saga compensation gaps, and outbox relay lag β we volunteer:
Problem: In high-throughput databases (thousands of writes/sec), if the background outbox event relay crashes, the local `outbox` table continues accumulating events rapidly, eventually bloating database disks and degrading queries.
Mitigation: Implement automated, high-speed purging or partition truncation of processed records (`WHERE published = true`) in the outbox table.
Problem: Introducing centralized API gateways or sidecar proxies (Envoy) adds extra network serialization and deserialization hops to every request, raising baseline tail latencies (P99).
Mitigation: Deploy lightweight, high-performance C++ sidecars, terminating SSL at edge layers and utilizing high-concurrency gRPC protocols for internal communication.
8. Common HLD Usage
Legacy modernization, e-commerce checkout, and event-driven architectures use these patterns:
| Modernization Scenario | Pattern Selection | Architectural Rationale |
|---|---|---|
| Legacy Monolith Modernization | Strangler Fig Migration | An API gateway intercepts /orders endpoints, routing them to a new isolated microservice fleet, keeping /users pointing to the legacy app. |
| Reliable E-Commerce Invoicing | Transactional Outbox + Debezium CDC | Order updates write to database orders and outbox event tables inside a single SQL transaction. CDC relay tails WAL logs to stream events to Kafka. |
9. Decision Signals
Reach for strangler when migrating live traffic; saga/outbox when cross-service writes must be reliable:
- You are designing legacy codebase modernizations where rewriting the entire monolith at once is too risky.
- You must coordinate multi-step workflows spanning different service databases while maintaining consistency.
- You need to publish transactional events to message brokers without introducing dual-write failure points.
11. Deep Dive (Optional)
The Anti-Corruption Layer (Domain Boundary Protection)
When strangling a legacy monolith, the new microservice must often query legacy tables to fetch user attributes. However, legacy datastores frequently feature convoluted schemas that violate the clean, modern domain model of the new microservice.
Solution: Anti-Corruption Layer (ACL)
- Place a dedicated Anti-Corruption Layer adapter between the legacy system and the new microservice.
- When the new microservice requests a profile:
New Service Request: GET /users/123 -> returns clean JSON
- The ACL catches the query, maps it to complex legacy calls, translates messy relational table layouts into a clean JSON structure, and returns it.
This prevents legacy domain models from leaking into and corrupting the new microservice codebase, protecting domain boundaries during modernizations.
Review
How helpful was this walkthrough?
Click a star to rate. We actively use this feedback to refine and update our system design content.
Discussion
Share your thoughts, ask questions, or help others.