Using (CQRS • Saga • Azure Service Bus • Circuit Breaker • Adapter • Patterns & Best Practices)
TL;DR (What you'll build)
A cloud-ready microservices system where each microservice:
- 
Is a .NET Core Web API (REST) exposing bounded-capability endpoints.
 - 
Uses CQRS: separate read model and write model (commands vs queries).
 - 
Coordinates complex business workflows using SAGA (via Azure Service Bus).
 - 
Communicates async via Azure Service Bus (topics/subscriptions or queues).
 - 
Uses Circuit Breaker (Polly) + retry/backoff to improve resilience.
 - 
Uses Adapter pattern for external systems and for infrastructure abstraction.
 - 
Front-end is an Angular SPA calling an API Gateway (or BFF) that routes to microservices.
 
Architecture overview (high level)
- 
API Gateway / BFF (optional): Single public endpoint, routing, auth, aggregation.
 - 
Microservices (multiple): each with its own database (DB-per-service), own bounded context.
- 
Example services:
Orders,Payments,Inventory,Customers,Shipping. 
 - 
 - 
Azure Service Bus: topics for publish/subscribe events, queues for commands/tasks.
 - 
CQRS: Commands handled by write-side; queries served by optimized read DB (e.g., read replica or denormalized store like CosmosDB/SQL).
 - 
Sagas: Orchestrate long-running transactions (compensations) via events/messages.
 - 
Polly: Circuit Breaker + Retry + Timeout for outbound HTTP/Bus calls.
 - 
Monitoring & Logging: Application Insights, centralized logs (ELK/Serilog sink).
 - 
CI/CD & Hosting: Build pipeline -> container images -> AKS / App Service.
 
Diagram (textual):
Core design principles
- 
Single Responsibility & Bounded Contexts — keep microservices small and focused.
 - 
DB-per-service — avoid shared DB to reduce coupling.
 - 
Event-driven — communicate asynchronously where eventual consistency is acceptable.
 - 
Idempotency — message handlers must be idempotent.
 - 
Id-based correlation — include correlation IDs in messages for tracing.
 - 
Resilience — use bulkheads, circuit breakers, retries, timeouts.
 - 
Observability — structured logs, distributed tracing (W3C TraceContext).
 
Key patterns & how to apply them
1. CQRS (Command Query Responsibility Segregation)
- 
Write side: handles commands (
POST /orders→CreateOrderCommand). Validations and state changes happen here. - 
Read side: optimized projection used for queries (
GET /orders/123). Read DB is updated by event subscribers. - 
Implementation:
- 
Commands go to controllers → Command Handlers (MediatR is common).
 - 
After state change, publish domain event (to Azure Service Bus).
 - 
Event consumers update read model (denormalized tables or NoSQL).
 
 - 
 
Example files/folders:
2. Saga (long-running transactions)
- 
Use Saga to coordinate multi-step flows (e.g., order -> reserve inventory -> charge payment -> ship).
 - 
Two approaches:
- 
Choreography: each service reacts to events. Simple but can be hard to reason about for complex flows.
 - 
Orchestration: Saga Orchestrator service sends commands to participants and listens for replies/events. Easier to visualize and control compensations.
 
 - 
 - 
Implementation with Azure Service Bus:
- 
Orchestrator publishes
ReserveInventoryCommandto a queue. - 
Inventory service replies
InventoryReservedEventorInventoryReserveFailedEvent. - 
Orchestrator then issues
ChargePaymentCommandorCompensateOrderCommand. 
 - 
 - 
Always plan for compensation (rollback-like steps) when a later step fails.
 
3. Azure Service Bus (Messaging)
- 
Use Topics + Subscriptions for publish/subscribe; Queues for point-to-point commands.
 - 
Message schema:
- 
MessageId,CorrelationId,CausationId,MessageType,Payload. 
 - 
 - 
Use dead-letter queues for poison messages and implement retries & DLQ handling.
 
4. Circuit Breaker & Resilience (Polly)
- 
Wrap all outbound network calls (HTTP, DB, Service Bus operations) with retry + jittered backoff + circuit breaker.
 - 
Typical policy: Retry (3 attempts, exponential backoff) + Circuit Breaker (open after 5 failures for 30s) + Timeout (5s).
 - 
Example: use
HttpClientFactorywith Polly policies. 
5. Adapter Pattern
- 
Use adapters to isolate external/specific client libs (e.g., Azure Service Bus SDK, Payment Gateway SDK) from your domain.
 - 
Define an interface (e.g.,
IPaymentGateway) and implementStripeAdapter/DummyAdapter. This supports testability and swapping providers. 
6. Repository + Unit of Work (when needed)
- 
Use repository for aggregate persistence; Unit of Work if multiple repositories within same DB transaction (but prefer small transactions).
 
7. Anti-Corruption Layer
- 
When integrating with legacy systems, use an adapter/anti-corruption layer to map incompatible models.
 
Concrete implementation steps
1. Set up projects
Solution example:
2. Shared contracts & DTOs
Create a Shared/Messaging project with message types (events/commands) used across services. Strongly-typed messages reduce coupling.
Example OrderCreatedEvent:
3. Implement CQRS in a service (Orders example)
- 
Use MediatR for intra-service command/handler pattern.
 - 
Controller:
 
- 
CommandHandler:
 
4. Publish/Subscribe (Azure Service Bus)
- 
Implement
IMessageBusadapter that wraps Azure Service BusServiceBusClient. - 
For publishing events:
 
- 
For subscriptions, create background services (hosted services) to process messages and project read model.
 
5. Saga Orchestration (example flow)
- 
OrderspublishesOrderCreatedEvent. - 
Saga.Orchestratorsubscribes. OnOrderCreated:- 
Send
ReserveInventoryCommandtoInventoryqueue. - 
Wait for
InventoryReservedEventorInventoryReserveFailedEvent. - 
If reserved, send
ChargePaymentCommandtoPayments. - 
If payment succeeds, send
ShipOrderCommandtoShipping. - 
If any step fails, run compensating actions (e.g.,
ReleaseInventoryCommand,RefundPaymentCommand) and mark orderFailed. 
 - 
 
Orchestrator pattern: implement state persistence for saga instances (e.g., in CosmosDB/SQL). Store Saga state keyed by CorrelationId.
6. Circuit Breaker with HttpClientFactory + Polly
Register in Program.cs:
7. Angular front-end (simple BFF pattern)
- 
Angular calls API Gateway/BFF endpoints which route to microservices.
 - 
Use typed services, interceptors for auth (JWT) and correlation headers.
 
Example Angular service:
Add an HTTP interceptor to send x-correlation-id header and Authorization bearer token.
8. Idempotency & Message deduplication
- 
Keep
ProcessedMessagetable withMessageIdto ignore duplicate message deliveries. - 
Use Service Bus message-id + dedupe logic.
 
9. Testing
- 
Unit test command handlers and domain logic.
 - 
Integration tests for message flows (use in-memory or test instance of Service Bus or use the Azure Service Bus emulator).
 - 
Contract tests for message contracts.
 
10. Observability, Monitoring & Health
- 
Use Application Insights (or OpenTelemetry) for distributed tracing and metrics.
 - 
Add Health Checks endpoints and Kubernetes liveness/readiness probes.
 - 
Structured logging with Serilog, sink to central store.
 
Deployment & CI/CD (short)
- 
Dockerize each service.
 - 
Build pipeline: build -> test -> image -> push to ACR.
 - 
Deploy pipeline: pull image -> AKS (Kubernetes manifests) or Azure App Service.
 - 
Use Helm charts for Kubernetes; include config via ConfigMaps and secrets via Azure Key Vault.
 - 
Use canary / blue-green with ingress controller and feature flags (LaunchDarkly or open-source).
 
Practical tips & pitfalls
- 
Do not share a single database across services — this creates high coupling.
 - 
Prefer eventual consistency; design UIs to show pending states (e.g., "Payment Processing").
 - 
Compensation is not rollback — design compensating actions carefully.
 - 
Keep messages small and versionable — maintain backward compatibility.
 - 
Start with choreography for simple flows; move to orchestrator for complex flows requiring centralized control.
 - 
Use feature toggles while deploying new message flows.
 
Minimal code sample: publish event to Service Bus (adapter)
Folder structure suggestion (service-level)
Checklist before go-live
- 
Message contracts versioned & documented.
 - 
Idempotency & DLQ handled.
 - 
Circuit breakers instrumented.
 - 
Health checks + readiness gates.
 - 
Logging and distributed tracing configured.
 - 
Saga persistence & compensations tested.
 - 
Secure secrets (Key Vault) and communication (TLS, JWT).
 
Suggested next steps (practical small milestones)
- 
Create a
Shared.Messagingproject with event/command contracts. - 
Scaffold
Ordersservice with basic create order command and publisher (no Saga yet). - 
Create
Inventoryservice subscriber to update read model. - 
Add Azure Service Bus adapter and test end-to-end message flow locally (or in dev subscription).
 - 
Implement a simple saga orchestrator for a 3-step flow (inventory → payment → shipping).
 - 
Add Polly policies and instrument logging/tracing.
 - 
Dockerize and deploy to a dev cluster.