Skip to content
Konstantin Lepeshenkov edited this page Mar 8, 2026 · 57 revisions

Installing from NuGet

ThrottlingTroll works with ASP.NET Core, Azure Functions, Azure Functions with ASP.NET Core Integration and, in fact, can be used in any .NET project.

Depending on the platform your project is using, you need to install the correct ThrottlingTroll's NuGet package:

ASP.NET Core Azure Functions Generic .NET
Package: ThrottlingTroll ThrottlingTroll.AzureFunctions ThrottlingTroll
Sources: ThrottlingTroll.AspNet ThrottlingTroll.AzureFunctions ThrottlingTroll.Core
Samples: ThrottlingTrollSampleWeb ThrottlingTrollSampleFunction ThrottlingTrollSampleAspNetFunction ThrottlingTrollSampleInProcFunction ThrottlingTrollSampleDotNet6InProcDurableFunction (no dedicated sample project yet)

Note that egress rate limiting functionality (self-limiting HttpClient) can actually be used in any .NET project, and for that you just need to install this ThrottlingTroll package.

[Ingress] How to initialize and configure

You will need to call one or another form of .UseThrottlingTroll() method at your service's startup. Which version of it to call depends on which way of configuring rules/limits/settings you prefer. Four different ways are supported:

You can combine all four approaches in the same solution - ThrottlingTroll will just make up an aggregate of all rules and settings configured in one way or another. E.g. it might be useful to define some global limits statically or declaratively, and then fine-tune them on-the-go via a GetConfigFunc.

The current effective set of rules and settings is always available to your code via this.HttpContext.GetThrottlingTrollConfig() or request.FunctionContext.GetThrottlingTrollConfig() extension methods.

[Egress] How to initialize and configure

ThrottlingTroll allows you to configure and use a self-limiting HttpClient (the one that automatically returns an error response without making the actual HTTP call, once a configured limit is exceeded). You can initialize those HttpClient instances in three different ways:

  • Statically, aka via appsettings.json/host.json. Simplest.
  • Programmatically. Allows to have any kind of complicated initialization logic.
  • Reactively. You provide a routine, that fetches limits from wherever, and an IntervalToReloadConfigInSeconds for that routine to be called periodically by ThrottlingTroll. Allows to reconfigure rules and limits on-the-fly, without restarting your service.

[Generic, aka usable in any .NET project] How to initialize and configure

Just create an instance of ThrottlingTroll class and provide rules and limits as ctor's parameters.

Alternatively, use .AddThrottlingTroll() extension method to add an instance of IThrottlingTroll to your DI container. This option will also automatically pick rules and limits from your app config.

Then use IThrottlingTroll.WithThrottlingTroll() methods to limit your payloads.

Note that if Algorithm value is not specified in config settings, the default FixedWindow will be used.

By default, counters are stored in MemoryCacheCounterStore (in local memory).

Other out-of-the-box Counter Stores are:

You can use one of them, or you can create and use your own custom implementation of ICounterStore interface.

To configure a Counter Store to be used:

EITHER put an instance of it into your DI container:

builder.Services.AddSingleton<ICounterStore>(
    provider => new MyCounterStore(...)
);

OR provide it via UseThrottlingTroll() method:

app.UseThrottlingTroll(options =>
{
    options.CounterStore = new MyCounterStore(...);
});

NOTE, that ICounterStore implementations are supposed to be thread-safe.

Logging

By default, ThrottlingTroll will try to get and use an ILogger instance from your DI container.

Instead you can provide your custom logging routine, e.g.:

app.UseThrottlingTroll(options =>
{
    options.Log = (level, msg) => 
    {
        Console.WriteLine($"Severity: {level}. Message: {msg}");
    };
});

Exception handling

The way internal ThrottlingTroll's exceptions are handled is controlled by RateLimitMethod.ShouldThrowOnFailures setting.

For most rate limiting algorithms the default value for that setting is false, but for Semaphore rate limiter the default value is true. You can always configure this value explicitly:

app.UseThrottlingTroll(options =>
{
    // ...

    options.Config = new ThrottlingTrollConfig
    {
        Rules = new[]
        {
            new ThrottlingTrollRule
            {
                LimitMethod = new FixedWindowRateLimitMethod
                {
                    PermitLimit = 1,
                    IntervalInSeconds = 2,
                    ShouldThrowOnFailures = true
                }
            }
        }
    };

    // ...
});

When ShouldThrowOnFailures is set to false, ThrottlingTroll will log its internal exceptions and allow the request to be further processed. This means that, if e.g. you are using Redis counter store and your Redis instance is malfunctioning, the rate limiting will not be applied.

When ShouldThrowOnFailures is set to true, ThrottlingTroll will log and rethrow its internal exceptions. This means that, if e.g. you are using Redis counter store and your Redis instance is malfunctioning, your service will be broken.

Telemetry

Since version 7.3 ThrottlingTroll is instrumented with OpenTelemetry. Here is how to subscribe to ThrottlingTroll's metric and trace sources:

var otel = builder.Services.AddOpenTelemetry();
  
otel.WithMetrics(metrics =>
{
    //...
  
    metrics.AddMeter("ThrottlingTroll");
});
  
otel.WithTracing(tracing =>
{
    //...
  
    tracing.AddSource("ThrottlingTroll");
});

, then configure an exporter to your favourite observability tool - and you should see ThrottlingTroll's metrics and traces there.

Here is a sample trace (as it appears in Azure Monitor):

image

List of metrics (counters) emitted by ThrottlingTroll's meter:

  • throttlingtroll.ingress.rules_matched - counts how many rate limiting rules were matched by incoming requests.
  • throttlingtroll.ingress.requests_throttled - counts how many incoming requests were throttled (hit the limit).
  • throttlingtroll.egress.rules_matched - counts how many rate limiting rules were matched by outgoing requests.
  • throttlingtroll.egress.requests_throttled - counts how many outgoing requests were throttled (hit the limit).
  • throttlingtroll.internal_failures - counts how many internal failures ThrottlingTroll experienced.
  • throttlingtroll.get_config_func_successes - counts how many times ThrottlingTrollOptions.GetConfigFunc was successfully called.
  • throttlingtroll.get_config_func_failures - counts how many times ThrottlingTrollOptions.GetConfigFunc failed.

Clone this wiki locally