Resilient HTTP Clients in .NET 8

Resilient HTTP Clients in .NET 8

Building resilient applications is crucial, and part of that resiliency is making sure your applications outgoing http requests are covered. The .NET go to solution used to be Polly, an open source project to add resiliency to your API clients. Now, with .NET 8, Microsoft has taken things a step further by baking resiliency directly into the framework itself, powered by Polly under the hood. In this post, I’ll walk you through how resiliency is built right into .NET 8, showing you how it works and how it helps developers build applications that keep running smoothly, even when things go sideways.


Why is resilience important?

Resilience is crucial because it helps mitigate the impact of unexpected issues, ensuring your application stays functional and delivers a smooth user experience—even when things go sideways.

Take this real-world example: we had a commonly-used request to a third-party service that, on occasion, would start timing out. Normally, a few timeouts here and there were no big deal—our system would handle them gracefully, allowing users to retry as needed. But then, things escalated: every single request to this service started timing out. Suddenly, what used to be quick, millisecond responses turned into painfully long delays. Our server got backed up with a flood of stalled requests, and before we knew it, the entire system was grinding to a crawl.

In hindsight, we figured out that the root issue was with the third-party service, which was beyond our control. But we had no fallback, no resiliency built in. No circuit breakers, no retry limits, nothing to shield us from the dependency that we've been taking for granted for too long. Our application was an oak, not a willow.

Needless to say, resiliency became a top priority. Thankfully, the open-source library Polly helped us to quickly implement a solution, turning those third-party failures from moments of doom into distant memories.

For those who’ve noted that asking users to redo actions due to transient errors isn’t ideal for user experience, a great benefit is that this approach also enhances that aspect.


Resiliancy strategies

"Systems can fail — but resilient ones make sure your users never notice."

Picture this: you're in your car, engine humming, waiting for your wife to get ready. You tap the horn — a gentle signal saying, "I'm ready when you are." That horn? It's your HTTP request. And just like waiting for a response from an external API, you’re now waiting.

What happens next depends on how long it takes — and how well you’ve planned for the delay:


⏳ Set a Timeout

If she’s taking her time choosing the right shoes, maybe it’s smarter to shut off the engine. No point burning fuel endlessly. In software terms, long-running requests shouldn't hang forever. A timeout helps cut your losses and avoid clogging up the system. Sometimes it's better to exit gracefully than wait indefinitely.


🔁 Retry Temporary Failures

Maybe she just didn’t hear the first honk. A quick second tap might do the trick (though I’m not saying that’s always wise). Similarly, not every failed HTTP request is final. A brief glitch, a dropped connection — a retry might be all it takes to recover smoothly, without the user even noticing something went wrong.


🚫 Circuit Break When Things Go Really Bad

Still no sign of her? At some point, you realize honking won’t help — maybe she’s styling her hair now. Best to step back, grab a coffee, and try again later. In resilient systems, that’s the circuit breaker pattern: when a remote service keeps failing, stop calling it for a while. Give it space to recover, and spare your own system the wasted effort.


🛟 Fallbacks Save the Day

Now, let’s say coffee’s done and she still isn’t ready — maybe it’s time to go upstairs and help (or at least pretend to). In code, that’s your fallback: a backup plan that kicks in when the main route fails. Maybe show cached data, or a friendly message, or even switch to a different service.


Resilience isn't about perfection — it's about being ready for the imperfections that will happen. Timeouts, retries, circuit breakers, and fallbacks aren't just nice-to-haves. They're what separate robust systems from brittle ones.

Want a snappy ending too? Here's one:

Build for failure — because success depends on how well you recover.

Microsoft ❤️ Polly

For years, an open source project named Polly was the go-to solution to work these strategies into an application. However, after a teamup with the Polly community, Microsoft worked the v8 version of Polly into .NET 8's resiliancy libraries. The Microsoft.Extensions.Http.Resilience package provides a concise, HTTP-focused layer atop the Polly library, enhancing it with features like telemetry, dependency injection support, and options-based configuration.


The basics


When building applications that make HTTP requests to external services, ensuring resilience is crucial to handle failures gracefully and improve the user experience. .NET provides a powerful way to configure resilient HTTP clients using libraries like Polly through Microsoft.Extensions.Http.Resilience. Here's how you can configure a resilient HTTP client with built-in strategies such as timeouts, retries, and circuit breakers.

dotnet add package Microsoft.Extensions.Http.Resilience --version 8.0.0        


Article content
Standard Resilience Handler
Article content
Custom Handler

In summary:

  • Standard handler is a predefined resilience strategy provided by libraries, meant for common use cases.
  • Custom handler allows you to configure and define your own set of resilience strategies tailored to your specific needs.

To view or add a comment, sign in

More articles by Abdulwaisa Al Nuaimi

Insights from the community

Others also viewed

Explore topics