ConduitSharp.RateLimit.SlidingWindow 2.0.0

dotnet add package ConduitSharp.RateLimit.SlidingWindow --version 2.0.0
                    
NuGet\Install-Package ConduitSharp.RateLimit.SlidingWindow -Version 2.0.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="ConduitSharp.RateLimit.SlidingWindow" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ConduitSharp.RateLimit.SlidingWindow" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="ConduitSharp.RateLimit.SlidingWindow" />
                    
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 ConduitSharp.RateLimit.SlidingWindow --version 2.0.0
                    
#r "nuget: ConduitSharp.RateLimit.SlidingWindow, 2.0.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 ConduitSharp.RateLimit.SlidingWindow@2.0.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=ConduitSharp.RateLimit.SlidingWindow&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=ConduitSharp.RateLimit.SlidingWindow&version=2.0.0
                    
Install as a Cake Tool

ConduitSharp.RateLimit.SlidingWindow

A drop-in rate-limit algorithm (IRateLimiter) that replaces ConduitSharp's built-in fixed-window limiter with a sliding log.

Why

Fixed windows are cheap but bursty at the seam. With maxRequests: 5, windowSeconds: 60, a caller can spend all 5 at 11:00:59 and another 5 at 11:01:00 — 10 requests in one second, twice the nominal rate, entirely within the rules. The window resets on an aligned boundary, and the boundary does not care how recently you spent your quota.

A sliding log keeps the timestamp of every permit still inside the window, so the limit holds at every instant rather than only the aligned ones. The tests assert exactly this — the same burst, refused here and allowed by the fixed window.

The trade is memory: O(maxRequests) timestamps per active key against the fixed window's single counter. Worth it for expensive endpoints where the burst is what you are paying for; not worth it for a coarse per-minute quota over cheap reads.

Use it

Build and drop the DLL in the gateway's plugins/ directory. Discovery is automatic — the same seam ConduitSharp.RateLimit.RedisProtocol uses, and the last registration wins:

dotnet build -c Release
cp src/ConduitSharp.RateLimit.SlidingWindow/bin/Release/net10.0/ConduitSharp.RateLimit.SlidingWindow.dll \
   /path/to/gateway/plugins/

No routes.json change. The rate-limit plugin keeps its existing config — windowSeconds, maxRequests, keyHeader all mean the same thing; only when a permit frees changes:

{
  "name": "rate-limit",
  "config": { "windowSeconds": 60, "maxRequests": 5, "keyHeader": "X-Api-Key" }
}

Retry-After follows the algorithm automatically: the fixed window answers "seconds to the next boundary", this answers "seconds until your oldest request ages out".

Two seams, not one

Interface Change it to…
Algorithm IRateLimiter alter what "over the limit" means (this package)
Counter backend IRateLimitStore share counters across replicas (RateLimit.RedisProtocol)

They are independent because the reasons to change them are. Note this package does not use IRateLimitStore: that interface counts hits per aligned window id, which is precisely the model a sliding log rejects. An algorithm is free to keep state no store can express — which is why the two are separate seams rather than one.

The consequence: state here is per-process, so quotas are per replica. Behind a load balancer, N replicas mean up to N× the quota. A distributed sliding log needs a backend that can hold a per-key timestamp log (e.g. a Redis sorted set) — a worthwhile extension, and not what this example is for.

Product Compatible and additional computed target framework versions.
.NET 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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 113 8/14/2026
1.0.0 110 7/25/2026