This project demonstrates how to build a resilient .NET 8 API using HttpClientFactory
, and Polly to handle instability in external services using proven resilience patterns.
This PoC simulates integration with an unreliable external system, showcasing key resilience patterns commonly used in production APIs:
- Retry with exponential backoff
- Timeout to avoid hanging requests
- Circuit Breaker to prevent cascading failures
- Fallback with configurable message
- Structured logging and retry tracking
- Health check for upstream dependency
The API exposes a resilient endpoint to retrieve the status of an order. Internally, it delegates to a service layer, which interacts with a simulated unstable dependency.
GET /order/status/{orderId}
↓
OrderStatusService
↓
ExternalOrderStatusClient (HttpClient + Polly)
↓
Simulated API: /external/status/{orderId}
Policies are composed using Policy.WrapAsync(...)
, demonstrating how multiple layers of protection can be applied to external HTTP calls.
WaitAndRetryAsync
: retries transient failures with backoffTimeoutAsync
: aborts calls exceeding 5 secondsCircuitBreakerAsync
: opens the circuit after 2 consecutive failuresFallbackAsync
: returns a safe default response when everything else fails
WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(200 * attempt)
)
When all else fails, the fallback provides a graceful degradation response:
{
"orderId": "123",
"status": "The service is temporarily unavailable. Please try again later."
}
Response status: 503 Service Unavailable
The /health
endpoint checks the availability of the external service via /external/status/teste
and reports:
- ✅
Healthy
– response is 200 ⚠️ Degraded
– response is an error- ❌
Unhealthy
– exception or timeout occurred
dotnet build
dotnet run --project src/OrderStatusResilience.Api
Then open your browser at:
https://localhost:{port}/swagger
GET /order/status/{orderId}
– resilient endpoint using retry, timeout, circuit breaker and fallbackGET /external/status/{orderId}
– simulated unstable dependency (random success or failure)GET /health
– verifies external system availability