Back to solution architecture

Solution architecture

Common design patterns

Reusable solutions to the problems every distributed system runs into

Resilience patterns

Every dependency will fail at some point. Resilience patterns decide whether that becomes a blip or an outage.

A circuit breaker at work

Caller
Closed
Service
Consecutive failures

Closed

Calls pass through and failures are counted.

Open

Calls fail fast with a fallback; the service gets time to recover.

Half-open

One trial call decides: success closes the breaker, failure opens it again.

SuccessFailedFallbackTrial call· Illustrative example
After three failures the breaker opens and calls fail fast with a fallback instead of piling up. After a cooldown one trial call is let through; when it succeeds, traffic flows again.

Circuit breaker

Prevent cascading failures by stopping calls to failing services. After failures exceed threshold, circuit "opens" and requests fail immediately. Periodically test if service recovered (half-open state).

Retry pattern

Automatically retry failed operations with exponential backoff. Useful for transient failures (network glitches, temporary unavailability). Implement max retry limits and idempotency.

Bulkhead pattern

Isolate resources (connection pools, threads) so failure in one area doesn't consume all resources. Like watertight compartments in a ship.

Integration patterns

API gateway pattern

Single entry point for all client requests. Gateway routes, transforms, and aggregates requests to backend services.

  • Benefits: Simplified client code, centralized security, request/response transformation
  • Implementation: Azure API Management, Application Gateway, custom gateway with Ocelot

Backends for frontends (BFF)

Separate backend services optimized for each frontend (web, mobile, IoT).

  • Benefits: Tailored responses, independent evolution, better performance
  • Use cases: Multi-platform applications with different UX requirements

Strangler fig pattern

Incrementally migrate legacy systems by routing requests to new services while gradually replacing old functionality.

  • Benefits: Low-risk modernization, parallel operation, gradual validation
  • Implementation: Routing layer (API gateway) directs traffic based on feature flags

Data management patterns

Database per service

Each microservice owns its database. No shared databases across services. Data synchronization via events or APIs.

CQRS (command query responsibility segregation)

Separate models for reads and writes. Write model optimized for consistency, read models denormalized for query performance.

Implementation: SQL for writes, Cosmos DB for reads, Event Grid for synchronization

Saga pattern

Manage distributed transactions across microservices using compensating transactions. Orchestration (central coordinator) or choreography (event-driven) approaches.

Ready to design your solution architecture?

Let's discuss how strategic architecture can align your technology investments with business objectives while ensuring scalability and reliability.