# ASP.NET Core Rate Limiting with gRPC

ASP.NET Core with .NET 7 adds an interesting new feature: rate limiting. In this post, I will look into how to apply rate limiting for [gRPC](https://learn.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-6.0) services with ASP.NET Core.

> At the time of writing this post, the code samples are based on .NET 7 RC2.

## Rate Limiting with ASP.NET Core WebApi

We can find multiple demos on applying Rate Limiting on minimal APIs. However, it is less frequently demo-ed on how to apply rate limiting on controllers. Fortunately, the [documentation](https://learn.microsoft.com/en-us/aspnet/core/performance/rate-limit?view=aspnetcore-7.0) details this scenario. Let me quickly recap.

Add a rate limiter to the services. Here I add a sliding window rate limiter.

```csharp
builder.Services.AddRateLimiter(options =>
{
    options.AddSlidingWindowLimiter("myLimiter", options =>
    {
        options.Window = TimeSpan.FromSeconds(10);
        options.PermitLimit = 3;
        options.SegmentsPerWindow = 1;
    });
});
```

Add the rate limiter middleware to the HTTP pipeline:

```csharp
app.UseRateLimiter();
```

Apply `[EnableRateLimiting("myLimiter")]` or `[DisableRateLimiting]` at Controller level or on the action methods:

```csharp
[HttpGet]
[EnableRateLimiting("myLimiter")]
public int Get()
{
    return 1;
}
```

While `[EnableRateLimiting]` adds a policy to a certain action or controller, we can use the `[DisableRateLimiting]` attribute to disable the rate limiter: for example `[EnableRateLimiting]` may be added at the controller level, but a certain action should exempt of rate limiting; in this case add the `[DisableRateLimiting]` to the action that should not have the rate limiter.

## Rate Limiting with gRPC

As gRPC in .NET7 services also builds on top of ASP.NET Core, let us review how we can setup rate limiting for such services. The same way as for webapi project, I register the rate limiting dependencies:

```csharp
builder.Services.AddRateLimiter(options =>
{
    options.AddSlidingWindowLimiter("myLimiter", options =>
    {
        options.Window = TimeSpan.FromSeconds(10);
        options.PermitLimit = 3;
        options.SegmentsPerWindow = 1;
    });
});
```

In this example, a simple sliding window rate limiter is added. This rate limiter allows three requests through in a 10-second-long window. Above the limit (when there is no queue limit set), the default behavior returns *503 Service Unavailable* response.

Next add the rate limiter to the HTTP pipeline:

```csharp
app.UseRateLimiter();
```

To enable Rate Limiting for a gRPC service, we have multiple options. A similar approach to minimal API, we can add `RequireRateLimiting` on the `IEndpointConventionBuilder` in this case this is `GrpcServiceEndpointConventionBuilder`:

```csharp
app.MapGrpcService<SuperServiceImpl>().RequireRateLimiting("myLimiter");
```
Note, that the name of the rate limiting policy must be provided for the `RequireRateLimiting` method. However, we can also use attributes, similar as in controllers: add `[EnableRateLimiting("myLimiter")]` or `[DisableRateLimiting]` on the actual implementation of the generated gRPC base class.

```csharp
[EnableRateLimiting("myLimiter")]
public class SuperServiceImpl : SuperService.SuperServiceBase
{
    public override async Task<ResponseData> DoWork(RequestData request, ServerCallContext context)
    {
        return new ResponseData { Message = $"Hello {request.Message}" };
    }
}
```

We can add the above attributes onto the actual method implementation as well:

```csharp
[EnableRateLimiting("myLimiter")]
public override async Task<ResponseData> DoWork(RequestData request, ServerCallContext context)
{
    return new ResponseData { Message = $"Hello {request.Message}" };
}
```

When the rate limiter rejects a request, that manifests as an `RpcException` on a C# client side, with 503 Unavailable status code: 

`Grpc.Core.RpcException: 'Status(StatusCode="Unavailable", Detail="Bad gRPC response. HTTP status code: 503")'`

## Conclusion

Users can apply Rate Limiting on ASP.NET Core gRPC services on a similar approach as for webapis.