Retry-After pause
A throttle with Retry-After holds back all requests of the limiter, not only the one that failed.
MaxPauseAdaptive client-side rate limiting for .NET HttpClient. The limiter slows down on429, honors Retry-After, and climbs back when the server allows it.
dotnet add package Nall.RateLimiting.AdaptiveQuick start
Register a named limiter, add its handler to an HttpClient, and set the rates. Requests now wait for the limiter, and the limiter learns from each response.
builder.Services.AddAdaptiveRateLimiter("orders-api");
builder .Services.AddHttpClient<OrdersClient>(c => c.BaseAddress = new Uri("https://api.example.com/") ) .AddAdaptiveRateLimitHandler("orders-api");{ "AdaptiveRateLimiting": { "Limiters": { "orders-api": { "InitialUnitsPerMinute": 600, "MinUnitsPerMinute": 60, "MaxUnitsPerMinute": 1200 } } }}How it works
The request waits in a token bucket until its units are free.
The handler sends the request to the API through HttpClient.
A 429, or a 503 with Retry-After, is a throttle. A success that had to wait is a signal to grow.
The controller sets the next rate. A throttle also pauses for Retry-After.
Features
A throttle with Retry-After holds back all requests of the limiter, not only the one that failed.
MaxPauseAIMD (default) and CUBIC are built in. Write your own controller for a different curve.
IRateControllerA request can cost more than one unit. The estimator tells the cost before the request goes out.
IRequestCostEstimatorSeveral processes split one quota. Set a static count, or give a live source.
IInstanceCountSourceUnits, throttles, rejections, wait time, rate, queue and instances, ready for OpenTelemetry.
System.Diagnostics.MetricsNamed limiters bind from configuration and reload on change. The binding does not use reflection.
IConfigurationRate controllers
Adds a fixed step on success and multiplies the rate down on a throttle. Steady and easy to reason about.
Grows on a cubic curve around the last rate that failed. Uses more of the quota, with more throttles.
Model numbers: 15 minutes, 2 instances at 2,000 units/min each, quota 3,000 units/min with a 50% drop for 60 s.
Compare the controllers →Packages
Nall.RateLimiting.AdaptiveThe limiter, the HttpClient handler, the AIMD and CUBIC controllers, DI registration and metrics.
dotnet add package Nall.RateLimiting.AdaptiveNall.RateLimiting.Adaptive.MicrosoftGraphSharePoint resource-unit costs for Graph requests and $batch, throttled inner $batch responses and CSOM.
dotnet add package Nall.RateLimiting.Adaptive.MicrosoftGraphRun None, Fixed, AIMD and CUBIC against the same quota in your browser. Change the quota, the demand and the number of instances.