Architecture Patterns & System Design
Microservices Architecture Patterns
Microservices questions dominate modern architect interviews. Understanding decomposition strategies, communication patterns, and trade-offs is essential.
Microservices vs Monolith
Decision Framework
| Factor | Monolith Wins | Microservices Wins |
|---|---|---|
| Team Size | < 20 engineers | > 30 engineers |
| Domain Complexity | Single domain | Multiple bounded contexts |
| Deployment Cadence | Weekly releases | Daily/hourly releases |
| Scale Requirements | Uniform scaling | Component-specific scaling |
| Organizational Structure | Single team | Multiple autonomous teams |
Interview Question: When to Use Microservices
Q: "A startup has 8 engineers and wants to adopt microservices. What's your advice?"
A: Generally advise against microservices for small teams:
Reasons:
- Operational Overhead: Each service needs deployment, monitoring, logging
- Network Complexity: Distributed tracing, latency, failure handling
- Cognitive Load: 8 engineers can't deeply own many services
- Development Speed: Monolith allows faster initial development
Recommendation:
- Start with a modular monolith (clear internal boundaries)
- Use dependency injection and interfaces
- Extract services only when specific scaling needs emerge
- First candidates: high-scale features, different tech requirements
Service Decomposition
Domain-Driven Design (DDD) Approach
Bounded Contexts:
E-commerce Platform:
├── Catalog Context (Product, Category, Search)
├── Order Context (Order, Cart, Checkout)
├── Payment Context (Payment, Refund)
├── Shipping Context (Shipment, Tracking)
└── User Context (User, Authentication, Profile)
Decomposition Heuristics:
- Single Responsibility: Each service does one thing well
- Team Ownership: One team can own and deploy independently
- Business Capability: Aligned with business function
- Data Ownership: Each service owns its data
Interview Question: Service Boundaries
Q: "You're designing an e-commerce platform. Where do you draw service boundaries?"
A: Apply decomposition principles:
Service: Order Service
Responsibilities:
- Order lifecycle (create, update, cancel)
- Cart management
- Order validation
Does NOT include:
- Payment processing (Payment Service)
- Inventory check (Catalog Service - query only)
- Shipping (Shipping Service - event-driven)
Communication:
- Sync: Query Catalog for price/availability
- Async: Emit OrderCreated event → Payment, Inventory, Shipping
Communication Patterns
Synchronous Communication
REST over HTTP:
- Simple, widely understood
- Good for CRUD operations
- Challenge: Cascading failures
gRPC:
- Binary protocol, faster than REST
- Strong typing with Protocol Buffers
- Bidirectional streaming
- Better for internal service-to-service
Asynchronous Communication
Message Queues (SQS, RabbitMQ):
Producer → Queue → Consumer
- Point-to-point communication
- Load leveling
- Guaranteed delivery
Event Streaming (Kafka, Kinesis):
Producer → Topic → Multiple Consumers
- Publish-subscribe pattern
- Event replay capability
- Real-time processing
Interview Question: Sync vs Async
Q: "When would you choose async over sync communication?"
A:
| Use Case | Communication Style | Reason |
|---|---|---|
| Get product details | Sync (REST/gRPC) | User waiting, need immediate response |
| Place order | Async (Event) | Can background process, send confirmation |
| Send notification | Async (Queue) | User doesn't wait for email delivery |
| Payment processing | Sync (with timeout) | Need immediate result for checkout |
| Update search index | Async (Event) | Eventually consistent is acceptable |
Saga Pattern for Distributed Transactions
The Problem
Microservices can't use traditional ACID transactions across services.
Choreography-Based Saga
Each service listens for events and acts:
Order Service → OrderCreated Event
↓
Payment Service → PaymentCompleted Event
↓
Inventory Service → InventoryReserved Event
↓
Shipping Service → ShipmentCreated Event
Pros: Decoupled, scalable Cons: Hard to track overall flow, complex failure handling
Orchestration-Based Saga
Central orchestrator coordinates:
Saga Orchestrator:
1. Call Order Service → Create Order
2. Call Payment Service → Process Payment
3. Call Inventory Service → Reserve Items
4. Call Shipping Service → Create Shipment
On Failure at step 3:
- Compensate: Refund Payment
- Compensate: Cancel Order
Pros: Clear flow, easier debugging Cons: Orchestrator is single point of complexity
Interview Question: Saga Compensation
Q: "What happens if the Shipping Service fails after payment succeeds?"
A: Implement compensating transactions:
Happy Path:
Order → Payment → Inventory → Shipping ✓
Failure at Shipping:
Order ✓ → Payment ✓ → Inventory ✓ → Shipping ✗
Compensation:
1. Release Inventory (compensate reservation)
2. Refund Payment (compensate charge)
3. Cancel Order (or mark as failed)
4. Notify User (explain failure)
Key Principles:
- Compensations must be idempotent
- Store saga state for recovery
- Consider timeouts and retries before compensation
API Gateway Pattern
Responsibilities
- Request routing
- Authentication/Authorization
- Rate limiting
- Request transformation
- Response aggregation
- Caching
API Gateway Options
| Service | Cloud | Features |
|---|---|---|
| Amazon API Gateway | AWS | Lambda integration, throttling |
| Apigee | GCP | Analytics, developer portal |
| Azure API Management | Azure | Policies, developer portal |
| Kong | Multi-cloud | Plugin ecosystem, open source |
| AWS ALB | AWS | Simple routing, cost-effective |
Interview Question: BFF Pattern
Q: "Explain the Backend for Frontend (BFF) pattern."
A: Create specialized API gateways per client type:
Mobile App → Mobile BFF → Microservices
Web App → Web BFF → Microservices
Partner API → Partner BFF → Microservices
Benefits:
- Optimized payloads per client (mobile gets less data)
- Client-specific auth flows
- Independent evolution
When to Use:
- Significantly different client requirements
- Multiple teams own different clients
- Performance optimization needs
Architecture Principle: Start with a single API Gateway, extract BFFs only when client divergence justifies the overhead.
Next, we'll explore event-driven architecture patterns. :::