|
| 1 | +# Rate Limiting |
| 2 | + |
| 3 | +ASP.NET Zero includes a built-in **dynamic rate limiting** system that allows you to protect your API endpoints from abuse by controlling the number of requests clients can make within a given time window. Rate limiting policies are fully manageable through the administration UI and are applied dynamically at runtime — no application restart is required when policies change. |
| 4 | + |
| 5 | +## Enabling Rate Limiting |
| 6 | + |
| 7 | +Rate limiting can be enabled or disabled globally using the master toggle at the top of the Rate Limiting management page. Navigate to **Administration > Rate Limiting** to access it. |
| 8 | + |
| 9 | +<img src="images/features-rate-limiting-list.png" alt="Rate Limiting Policies" class="img-thumbnail" /> |
| 10 | + |
| 11 | +When rate limiting is disabled, no policies are enforced and all requests pass through without any rate checks. |
| 12 | + |
| 13 | +## Policy List |
| 14 | + |
| 15 | +The policies page displays all configured rate limit policies in a table with the following columns: |
| 16 | + |
| 17 | +- **Name** – A descriptive name for the policy |
| 18 | +- **Algorithm** – The rate limiting algorithm used (Fixed Window, Sliding Window, Token Bucket, or Concurrency) |
| 19 | +- **Partition Type** – How requests are grouped (By Client IP, By User, or By API Key) |
| 20 | +- **Permit Limit** – Maximum number of requests allowed within the time window |
| 21 | +- **Window (seconds)** – The time window duration in seconds |
| 22 | +- **Is Global** – Whether the policy applies to all endpoints |
| 23 | +- **Is Enabled** – Whether the policy is currently active |
| 24 | + |
| 25 | +You can filter policies using the search box and use the **Actions** button on each row to edit, toggle, or delete a policy. |
| 26 | + |
| 27 | +## Creating or Editing a Policy |
| 28 | + |
| 29 | +Click the **Create New Policy** button or select **Edit** from the Actions menu of an existing policy. The following modal will appear: |
| 30 | + |
| 31 | +<img src="images/features-rate-limiting-edit.png" alt="Create or Edit Rate Limit Policy" class="img-thumbnail" /> |
| 32 | + |
| 33 | +### Policy Fields |
| 34 | + |
| 35 | +| Field | Description | |
| 36 | +|-------|-------------| |
| 37 | +| **Policy Name** | A unique, descriptive name for the policy (e.g., "API Global Limit", "Login Endpoint Limit"). | |
| 38 | +| **Is Enabled** | Toggle to enable or disable this specific policy. | |
| 39 | +| **Algorithm** | The rate limiting algorithm to use. See [Algorithms](#algorithms) below. | |
| 40 | +| **Partition Type** | How to partition (group) incoming requests. See [Partition Types](#partition-types) below. | |
| 41 | +| **Is Global** | When enabled, the policy applies to all API endpoints. When disabled, you must specify an endpoint pattern. | |
| 42 | +| **Endpoint Pattern** | A URL pattern to match specific endpoints (only visible when Is Global is off). Supports wildcard `*` matching. For example: `/api/services/app/User/*` | |
| 43 | +| **Permit Limit** | The maximum number of requests allowed within the time window. | |
| 44 | +| **Window (seconds)** | The duration of the time window in seconds (used by Fixed Window and Sliding Window algorithms). | |
| 45 | +| **Queue Limit** | The number of requests that can be queued when the limit is reached. Set to `0` to reject immediately. | |
| 46 | +| **HTTP Status Code** | The HTTP status code returned when a request is rate limited. Default is `429` (Too Many Requests). | |
| 47 | +| **Custom Message** | An optional message returned in the response body when a request is rate limited. | |
| 48 | + |
| 49 | +### Algorithm-Specific Fields |
| 50 | + |
| 51 | +Depending on the selected algorithm, additional fields may be relevant: |
| 52 | + |
| 53 | +| Field | Algorithm | Description | |
| 54 | +|-------|-----------|-------------| |
| 55 | +| **Segments Per Window** | Sliding Window | Number of segments the window is divided into. Higher values provide smoother rate limiting. | |
| 56 | +| **Tokens Per Period** | Token Bucket | Number of tokens added to the bucket each replenishment period. | |
| 57 | +| **Replenishment Period (seconds)** | Token Bucket | How often tokens are added to the bucket. | |
| 58 | + |
| 59 | +## Algorithms |
| 60 | + |
| 61 | +ASP.NET Zero supports four rate limiting algorithms built on .NET's `System.Threading.RateLimiting`: |
| 62 | + |
| 63 | +### Fixed Window |
| 64 | + |
| 65 | +Divides time into fixed windows (e.g., 60-second intervals). Each window allows a set number of requests. The counter resets at the start of each new window. |
| 66 | + |
| 67 | +**Best for**: Simple, predictable rate limiting where occasional bursts at window boundaries are acceptable. |
| 68 | + |
| 69 | +**Example**: 100 requests per 60 seconds. |
| 70 | + |
| 71 | +### Sliding Window |
| 72 | + |
| 73 | +Similar to Fixed Window, but the window slides continuously rather than resetting at fixed intervals. The window is divided into segments, and the allowed request count is calculated based on the weighted sum of the current and previous segments. |
| 74 | + |
| 75 | +**Best for**: Smoother rate limiting that avoids burst issues at window boundaries. |
| 76 | + |
| 77 | +**Example**: 100 requests per 60 seconds with 6 segments (each segment is 10 seconds). |
| 78 | + |
| 79 | +### Token Bucket |
| 80 | + |
| 81 | +Maintains a "bucket" of tokens that is replenished at a fixed rate. Each request consumes one token. When the bucket is empty, requests are rejected or queued. The bucket can accumulate tokens up to the permit limit, allowing controlled bursts. |
| 82 | + |
| 83 | +**Best for**: APIs that need to allow short bursts of traffic while maintaining an average rate over time. |
| 84 | + |
| 85 | +**Example**: Bucket size of 100 tokens, replenishing 10 tokens every second. |
| 86 | + |
| 87 | +### Concurrency |
| 88 | + |
| 89 | +Limits the number of concurrent (simultaneous) requests rather than requests over a time window. This is useful for protecting resources that have limited parallel processing capacity. |
| 90 | + |
| 91 | +**Best for**: Endpoints that are resource-intensive and should limit how many requests are processed simultaneously. |
| 92 | + |
| 93 | +**Example**: Maximum 10 concurrent requests. |
| 94 | + |
| 95 | +## Partition Types |
| 96 | + |
| 97 | +Partition types determine how incoming requests are grouped for rate limiting: |
| 98 | + |
| 99 | +### By Client IP |
| 100 | + |
| 101 | +Requests are grouped by the client's IP address. Each unique IP address gets its own rate limit counter. This is the default partition type. |
| 102 | + |
| 103 | +### By User |
| 104 | + |
| 105 | +Requests are grouped by the authenticated user's identity. Each logged-in user gets their own rate limit counter. Anonymous requests fall back to IP-based partitioning. |
| 106 | + |
| 107 | +### By API Key |
| 108 | + |
| 109 | +Requests are grouped by the `X-API-Key` HTTP header value. This is useful for API consumers that authenticate using API keys. |
| 110 | + |
| 111 | +## Policy Matching |
| 112 | + |
| 113 | +When a request arrives, the system finds the matching policy using this priority: |
| 114 | + |
| 115 | +1. **Endpoint-specific policies** are checked first. The request path is matched against the `EndpointPattern` of non-global policies. |
| 116 | +2. If no endpoint-specific policy matches, the first **global policy** is applied. |
| 117 | +3. If no policy matches at all, the request passes through without rate limiting. |
| 118 | + |
| 119 | +Endpoint patterns support wildcard matching with `*`. For example: |
| 120 | + |
| 121 | +| Pattern | Matches | |
| 122 | +|---------|---------| |
| 123 | +| `/api/services/app/User/*` | All User service endpoints | |
| 124 | +| `/api/services/app/*/GetAll` | GetAll method on any service | |
| 125 | +| `/api/TokenAuth/*` | All authentication endpoints | |
| 126 | + |
| 127 | +## Caching and Performance |
| 128 | + |
| 129 | +Rate limiting policies are cached in memory for optimal performance. The cache is automatically invalidated whenever a policy is created, updated, deleted, or toggled, and when the global rate limiting setting is changed. This means policy changes take effect immediately without requiring an application restart. |
| 130 | + |
| 131 | +## Permissions |
| 132 | + |
| 133 | +Rate limiting management is controlled by the following permissions under **Administration > Rate Limiting**: |
| 134 | + |
| 135 | +| Permission | Description | |
| 136 | +|------------|-------------| |
| 137 | +| Rate Limiting | View rate limiting policies | |
| 138 | +| Create | Create new policies | |
| 139 | +| Edit | Edit existing policies | |
| 140 | +| Delete | Delete policies | |
| 141 | + |
| 142 | +## Configuration |
| 143 | + |
| 144 | +Rate limiting is built on top of .NET's `Microsoft.AspNetCore.RateLimiting` middleware. It is registered in the application's startup using the `AddDynamicRateLimiting()` extension method: |
| 145 | + |
| 146 | +```csharp |
| 147 | +services.AddDynamicRateLimiting(); |
| 148 | +``` |
| 149 | + |
| 150 | +And the middleware is applied in the request pipeline: |
| 151 | + |
| 152 | +```csharp |
| 153 | +app.UseRateLimiter(); |
| 154 | +``` |
| 155 | + |
| 156 | +The global enable/disable setting is stored in the application settings (`App.RateLimiting.IsEnabled`) and can be toggled from the UI without redeploying. |
0 commit comments