An introduction to the new rate-limiting middleware available in ASP.NET Core and how it compares to the AspNetCoreRateLimit package that solves the same task.
Since I learned that ASP.NET Core 7 and newer come with built-in rate limiting I have wanted to try it out. I finally had some time to check it out and here's what I've found so far. This introduces rate limiting in ASP.NET Core using both the built-in option and
A quick comment before we begin. I've blogged about this subject in the past, so I would recommend you to read through this post: Rate limiting API requests with ASP.NET Core and AspNetCoreRateLimit. In this post, I'll be comparing the built-in rate limiting feature in ASP.NET Core with
AspNetCoreRateLimit. I'll try to summarize the previous post here but for the full experience, consider reading both posts.
Rate-limiting in ASP.NET Core
Rate limiting in a web application is typically about ... well limiting the number of requests processed by the web application. For public APIs, you quickly need some way of limiting how many requests your users can make. There's a range of possibilities as to how to implement this, whether this is based on the client's IP address, an API key/token, or something third. To compare the examples in this post with the previous post about
AspNetCoreRateLimit, I'll implement rate limiting based on an API key.
To test out rate limiting, you will need .NET 7 or newer as well as the newest version of Visual Studio 2022 (currently the preview version is required to run .NET 7 apps).
Create a new application by running the following command:
dotnet new mvc
This creates a new MVC app. Rate limiting is not specific to ASP.NET Core MVC and can be used with minimal API and other types as well. In the new web application, install the
Microsoft.AspNetCore.RateLimiting NuGet package:
dotnet add package Microsoft.AspNetCore.RateLimiting
In the Program.cs file or (Startup.cs if don't like top-level statements) include rate limiting configuration like this:
This will tell ASP.NET Core that you want to configure the rate-limiting middleware with default settings. One default parameter that I would like to change up front is the status code that should be returned once the limit is reached. As a default
Microsoft.AspNetCore.RateLimiting will return a status code of
503. To change this to the (more correct IMO) status code
429, provide it as part of the options:
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
Next, we will need to tell the rate limit middleware when a limit is reached. This is done with a concept called policies. There's a range of different policy types available in the rate-limiting middleware. In this example, I want to limit the number of requests made with the same API key available in the URL like this:
To configure this, include the following policy:
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
options.AddPolicy("apikey", httpContext =>
return new FixedWindowRateLimiterOptions
Window = TimeSpan.FromHours(1),
PermitLimit = 10,
Let's go through the policy line-by-line. Policies are added by calling the
AddPolicy method. The first parameter is a policy name that we will need to reference this policy. This name will be used in the following step. Next, we provide a
Func that contains the actual code to run for this policy. In the callback, I check if the current request contains a query parameter named
api_key. In this case, we want rate limiting to apply. If not, rate limiting should not be run which is done by returning the result of
This rate limit policy is based on the fixed window limit. As already mentioned, there is a range of different policy types available, so make sure to check out the documentation before picking. The fixed window limiter will rate limit requests within a specified time window. In this example, I permit 10 requests per hour using the same API key. In the real world, your API should probably be able to handle more than 10 requests but for this, I have chosen a low number to easily test this in the browser.
The final step missing is to tell ASP.NET Core to use the middleware and where to apply the policy. There are attributes available to apply this to specific actions and/or controllers, but for this example, I'll apply it to everything:
RequestRateLimiting to the controller set up and including the policy name that we set in the previous step, ASP.NET Core will automatically run the policy against all controllers. Remember that only endpoints with an
api_key query parameter will apply here.
That's a very basic example of how rate limiting can be implemented with the
Microsoft.AspNetCore.RateLimiting package. Let's quickly revisit the
AspNetCoreRateLimit package to see how a similar policy can be implemented with that package.
AspNetCoreRateLimit is another rate-limiting library that has existed for years. It is maintained by Stefan Prodan and offers a very flexible model for implementing rate limiting in ASP.NET Core.
Start by installing the
AspNetCoreRateLimit NuGet package. If you are coding along, you can install it in the same project as before but having two rate-limiting packages installed isn't recommended for real code:
dotnet add package AspNetCoreRateLimit
A policy in
AspNetCoreRateLimit is implemented as configuration and a client resolver:
public class ElmahIoRateLimitConfiguration : RateLimitConfiguration
: base(ipOptions, clientOptions)
public override void RegisterResolvers()
public class ClientQueryStringResolveContributor : IClientResolveContributor
public Task<string> ResolveClientAsync(HttpContext httpContext)
var queryDictionary =
The code in this post has been updated to match the newest version of
AspNetCoreRateLimit. For more details on how
AspNetCoreRateLimit works, check out the previous post. The code above corresponds to the policy that we specified with the other package based on a query parameter named
These classes can be configured in the Program.cs file:
The additional singletons tell
AspNetCoreRateLimit how to store the current state. The limit and timespan from the previous example are provided through options:
options.GeneralRules = new List<RateLimitRule>
Endpoint = "*",
Period = "1h",
Limit = 10,
Again, we limit the requests to 10 per hour. The
* value for the
Endpoint property matches how we included the rate-limiting middleware to all controllers in the previous example.
The only missing part is calling the
That's it! A similar rate limit has now been implemented using
AspNetCoreRateLimit. Whether you prefer one package over the other, I will leave it up to you. These examples only show a limited set of capabilities from each package so I would recommend you to try out both and pick the one you prefer.
- 28th November, 2022: Initial version
This member doesn't quite have enough reputation to be able to display their biography and homepage.