NResilience 0.32.0

dotnet add package NResilience --version 0.32.0
                    
NuGet\Install-Package NResilience -Version 0.32.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NResilience" Version="0.32.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NResilience" Version="0.32.0" />
                    
Directory.Packages.props
<PackageReference Include="NResilience" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NResilience --version 0.32.0
                    
#r "nuget: NResilience, 0.32.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NResilience@0.32.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NResilience&version=0.32.0
                    
Install as a Cake Addin
#tool nuget:?package=NResilience&version=0.32.0
                    
Install as a Cake Tool

NResilience

Build NuGet Version NuGet Downloads .NET AOT License: MIT Docs

Prevent cascading failures in your .NET applications.

A struggling dependency can hang your requests, tie up your threads, and crash your application. Blind retries often make the problem worse by overwhelming the failing service. NResilience wraps your calls in retries, deadlines, attempt timeouts, and circuit breakers so your app degrades gracefully instead of crashing.

Why NResilience?

NResilience replaces complex fluent builders, confusing policy ordering, and mandatory Build() calls with simple values and C# with expressions.

  • No fluent builders. Configure policies using with expressions to change one setting while keeping the rest.
  • Sensible defaults. Get a working, retried HTTP call with one line of code.
  • One method for everything. Use RunAsync for HTTP calls, database queries, or queue reads.
  • Measured, not guessed. Attempt ceilings, circuit breaker trips, and even the concurrency limit are measured from what the dependency actually does, so you never guess a millisecond figure per dependency.
  • It knows when the problem is local. Saturation awareness stops those measurements learning from this process's own thread-pool queue - the one incident where every measured bound loosens at once while the dependency is fine.
  • Retry budget. A cap on retries as a fraction of traffic, on by default, so a fleet of clients cannot overwhelm a struggling dependency.
  • It reads the quota the dependency publishes. Most large APIs send how much allowance is left on every response. The HTTP handler reads it, keeps it per host, and refuses an attempt locally before the 429 - no rate to guess, because the dependency supplies it.
  • Hedging. When a call is slow, a duplicate request races it. Hedges pause while the dependency degrades, so they never pile onto a struggling service.
  • Deadline propagation. Deadlines travel across services: the gRPC interceptor sends grpc-timeout, and the ASP.NET middleware reads what a caller sent so outbound calls inherit it.
  • Criticality propagation. How much a request matters travels with it, so a backfill stops spending the retry capacity a checkout needs and is never hedged. The library carries the level and holds back amplification; what to shed stays your decision.
  • Drain-aware shutdown. When the host starts shutting down, calls stop retrying into the rollout and deadlines clamp to what is left of the grace period. On by default for registered policies, because a retry sent after the load balancer stopped routing here is one nobody will read the answer to.
  • Testable. Scripted callbacks, a recording listener, and fault injection make policies deterministic in tests.
  • Simulate before you ship. Run your policy against a modeled brownout on a virtual clock and read the load multiplier, the availability, and the p99 it produces. Five simulated minutes cost about as much as a unit test.
  • It explains itself. One call prints the worst-case timeline attempt by attempt and reports which measured terms are warm, so "how long can this call take?" has an answer you can read.
  • Telemetry. Every call raises one event carrying its verdict, retries, and delays; meters and an activity source expose them.
  • Production-ready. Built-in analyzers catch common mistakes, such as passing the wrong cancellation token.
  • Native AOT compatible. Zero external dependencies and no reflection.

Get started

Add NResilience to your project:

dotnet add package NResilience

For most HTTP scenarios, use the pre-configured client:

// Create one client for the application's lifetime
private static readonly HttpClient Client = HttpResilience.CreateClient();

private static async Task<User?> GetUserAsync(int id, CancellationToken cancellationToken) =>
    await Client.GetFromJsonAsync<User>(new Uri($"https://api.example.com/users/{id}"), cancellationToken);

Every call this client makes now uses three attempts with exponential backoff, a 30-second deadline, and HTTP-aware retry logic (for example, it retries a 503 but not a 404).

Simple configuration

Policies in NResilience are values. You can derive a new policy from an existing one using a with expression:

var slowPolicy = Resilience.Http with { Attempts = 5, Deadline = TimeSpan.FromSeconds(20) };

Beyond HTTP

Use RunAsync to wrap any asynchronous work, such as a database call or a third-party SDK:

var api = Resilience.Default;

string name = await api.RunAsync(attempt => db.ReadNameAsync(id, attempt), cancellationToken);

The attempt token is cancelled when the specific attempt hits its timeout, while the cancellationToken cancels the entire call.

Handle failures without exceptions

Use TryRunAsync to branch on the outcome instead of catching exceptions:

CallResult<User> result = await api.TryRunAsync(attempt => FetchAsync(attempt), cancellationToken);
User best = result.TryGetValue(out User? fetched) ? fetched : cache.LastKnownGood;

Performance and correctness

NResilience is built for high-performance .NET applications:

  • Low overhead. A flat execution path ensures that cost doesn't grow as you add more policy settings. Overhead is one allocation per call, and that ceiling is gated in CI.
  • Built-in analyzers. Seven diagnostics ship with the package to prevent silent failures.
  • Native AOT. Fully compatible with net8.0 and net10.0 trimming and AOT publishing.

Documentation

For more information, see these resources:

  • Quick start - get a retried HTTP call working in two minutes.
  • Key concepts - learn the core terminology.
  • Guides - see worked scenarios for common patterns.
  • Features - detailed explanations of every configuration option.
  • Migrating from Polly - a translation guide and behavioral differences.

Packages

Package Use case
NResilience The core library, HTTP handler, and analyzers.
NResilience.Extensions Dependency injection, configuration binding, metrics, and health checks.
NResilience.Testing Helpers for testing your policies, and fault injection.
NResilience.Grpc A gRPC client interceptor with status classification and grpc-timeout propagation.
NResilience.AspNetCore Middleware that reads the deadline and nested-retry marker a caller sent, so outbound calls inherit both, and an exception handler that maps NResilience exceptions to HTTP responses.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on NResilience:

Package Downloads
NResilience.Extensions

Dependency injection, configuration binding with hot reload, rate limiting and concurrency limiting, and OpenTelemetry-shaped metrics and traces for NResilience. Binds through a mutable DTO because the configuration binder silently ignores init-only properties.

NResilience.Testing

Test helpers for NResilience: a scripted callback, a recording telemetry listener, fault injection, and a deterministic simulator that measures what a policy costs a dependency over simulated minutes of a brownout.

NResilience.AspNetCore

The ASP.NET Core integration for NResilience: middleware that reads the deadline and the nested-retry marker a caller sent and publishes them for the rest of the request, so outbound policies are bounded by the time their caller is actually still waiting and report the retry loops they are nested inside, and an IExceptionHandler that maps the exceptions NResilience throws to the HTTP responses they mean - 504 for an exceeded deadline, 503 with Retry-After for a rejected call. A separate package because it is the only part of NResilience that requires ASP.NET Core.

NResilience.Grpc

The gRPC integration for NResilience: a client interceptor that runs a resilience policy around each call, classifies gRPC status codes, writes a per-attempt deadline the peer can read, scopes breakers and budgets per service, and reports nested retries. Retrying a gRPC client through the HTTP handler does nothing - every gRPC call is a POST - which is what this package exists to fix.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.32.0 197 9/10/2026
0.31.0 161 9/9/2026
0.30.0 165 9/9/2026
0.29.0 178 9/9/2026
0.28.0 165 9/9/2026
0.27.0 159 9/9/2026
0.26.0 164 9/8/2026
0.25.0 161 9/8/2026
0.24.0 160 9/8/2026
0.23.0 165 9/5/2026
0.22.0 170 9/5/2026
0.21.0 167 9/3/2026
0.20.0 138 9/3/2026
0.19.0 136 9/3/2026
0.18.0 140 9/1/2026
0.17.0 138 9/1/2026
0.16.0 139 9/1/2026
0.15.0 132 9/1/2026
0.14.0 242 8/30/2026
0.13.0 145 8/28/2026
Loading failed