> For the complete documentation index, see [llms.txt](https://coldbox-security.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://coldbox-security.ortusbooks.com/secure-your-app/route-middleware/throttle.md).

# Throttle

Rate limit routes with the Throttle middleware and the RateLimiter model.

`Throttle@cbsecurity` limits how many requests a client can make in a time window. Over the limit it answers `429 Too Many Requests` with a `Retry-After` header. Allowed requests get `X-RateLimit-Limit` and `X-RateLimit-Remaining` headers.

## Named Limiters

Define limiters once in your `cbsecurity` module settings and reference them by name:

```javascript
// config/ColdBox.bx
moduleSettings = {
    cbsecurity : {
        middleware : {
            throttle : {
                limiters : {
                    login : { maxAttempts : 5,   decaySeconds : 60 },
                    api   : { maxAttempts : 120, decaySeconds : 60, by : "user" }
                }
            }
        }
    }
}
```

```javascript
// config/Router.bx
route( "/login" ).middleware( "Throttle@cbsecurity" ).meta( { throttle : "login" } ).to( "sessions.create" )
```

An unknown limiter name throws `cbsecurity.MiddlewareMisconfigured`.

## Inline Limits

```javascript
route( "/search" )
    .middleware( "Throttle@cbsecurity" )
    .meta( { throttle : { maxAttempts : 30, decaySeconds : 60 } } )
    .to( "search.index" )
```

## Limiter Options

| Option          | Default                       | Description                                                                 |
| --------------- | ----------------------------- | --------------------------------------------------------------------------- |
| `maxAttempts`   | `60`                          | Requests allowed per window.                                                |
| `decaySeconds`  | `60`                          | The window length in seconds.                                               |
| `cacheProvider` | `default`                     | The name of the CacheBox cache that holds the counters.                     |
| `by`            | `ip`                          | `ip`, or `user` to count each logged in user. Guests fall back to their IP. |
| `name`          | limiter name or route pattern | Routes that share a `name` share one counter.                               |

Defaults for `maxAttempts`, `decaySeconds` and `cacheProvider` live in `middleware.throttle` and apply to anything you do not set.

{% hint style="warning" %}
Counters live in the CacheBox cache you choose. With more than one server, point `cacheProvider` at a shared cache (Redis, Couchbase or a database), otherwise every server counts on its own.
{% endhint %}

## RateLimiter

Use the model directly for limits that are not routes, like password resets or calls inside a service.

```javascript
limiter = getInstance( "RateLimiter@cbsecurity" )

if ( limiter.tooManyAttempts( "reset:#rc.email#", 3 ) ) {
    return event.renderData( statusCode : 429, data : "Try again in #limiter.availableIn( 'reset:#rc.email#' )# seconds" )
}
limiter.hit( "reset:#rc.email#", 3600 )
```

| Method                                               | Description                                              |
| ---------------------------------------------------- | -------------------------------------------------------- |
| `hit( key, decaySeconds, cacheProvider )`            | Record an attempt and return the attempts in the window. |
| `tooManyAttempts( key, maxAttempts, cacheProvider )` | Has the key reached its limit?                           |
| `attempts( key, cacheProvider )`                     | Attempts in the current window.                          |
| `remaining( key, maxAttempts, cacheProvider )`       | Attempts left, never below zero.                         |
| `availableIn( key, cacheProvider )`                  | Seconds until the window resets.                         |
| `clear( key, cacheProvider )`                        | Reset a key, for example after a successful login.       |

The window is fixed: it starts with the first hit and resets after `decaySeconds`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://coldbox-security.ortusbooks.com/secure-your-app/route-middleware/throttle.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
