PHPackages                             nimbly/throttler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. nimbly/throttler

ActiveLibrary

nimbly/throttler
================

A framework agnostic rate limiter.

1.1(5y ago)06.6kMITPHPPHP &gt;=7.3 || ^8.0

Since Oct 27Pushed 5y ago1 watchersCompare

[ Source](https://github.com/nimbly/Throttler)[ Packagist](https://packagist.org/packages/nimbly/throttler)[ RSS](/packages/nimbly-throttler/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (4)Versions (5)Used By (0)

Throttler
=========

[](#throttler)

[![Latest Stable Version](https://camo.githubusercontent.com/2cbad73a3c0c2736a3aa609cab8ffe4ee416a1baf2f6634a474549e4772723e4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6e696d626c792f5468726f74746c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/nimbly/throttler)[![Build Status](https://camo.githubusercontent.com/2a6a72f736ff9ec1256be31e1a990232780a7cc87a08c456bbde461453d0ef23/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6e696d626c792f5468726f74746c65722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/nimbly/Throttler)[![License](https://camo.githubusercontent.com/a2830d1a5c264177817b6718cd0cff969af38ce65a65db5c176c65b73409ea43/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6e696d626c792f5468726f74746c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/nimbly/throttler)

A framework agnostic request rate limiter.

Description
-----------

[](#description)

Throttler can rate limit on any data point you like: IP address, user ID, API key, or any other uniquely identifying information you have access to.

Installation
------------

[](#installation)

```
composer require nimbly/throttler
```

Usage
-----

[](#usage)

### Storage adapter

[](#storage-adapter)

You need a place to keep track of the hit counters - cache, database, or whatever. Create an instance of a storage adapter to be passed into the Throttler. See the **Available storage adapters** section further down for complete list of adapters.

```
$storageAdapter = new Throttler\Adapters\Redis(
    new Predis\Client('tcp://localhost:6379')
);
```

### Throttler

[](#throttler-1)

Instantiate Throttler by passing in a storage adapter instance.

```
$throttler = new Throttler($storageAdapter);
```

Constructor Options
-------------------

[](#constructor-options)

You may pass in an array of key =&gt; value pair options as the second parameter of the constructor.

```
$throttler = new Throttler($storageAdapter, ['key' => 'value']);
```

Supported options:

- **prefix** Prefix to apply to all keys and passed to the storage adapter. Defaults to **Throttler\\**.

Methods
-------

[](#methods)

`hit(string $id, int $limit, int $decay) : boolean`

Log a hit on the throttler incrementing the rate limit counter. Returns **true** on success and **false** on failure.

- **id** is the unique ID of the source of this request. This value can be any string you'd like: IP address, a user ID, etc.
- **limit** is the total number of requests allowed over the timespan defined by **decay**.
- **decay** is the timespan allowed in **seconds**.

This example allows **120** requests in a **60** second timespan per **IP address**.

```
if( $throttler->hit($request->ipAddress(), 120, 60) === false ){
    throw new TooManyRequestsHttpException(60, 'Slow it down man!');
}
```

---

`check(string $id) : int`

Check (but do not increment) the current rate limit counter for the given ID.

```
if( $throttler->check($request->user->id) >= $warningThreshold ){
    $response = $response->withHeader("X-Rate-Limit", "Warning");
}
```

Middleware
----------

[](#middleware)

Add the throttler to your Middleware (you're using Middleware, right?)

```
class ThrottleRequest implements SomeMiddlewareLibrary
{
    public function handle(Request $request, $next)
    {
        $storageAdapter = new Throttler\Adapters\Redis(
            new Predis\Client('tcp://localhost:6379')
        );

        $throttler = new Throttler($storageAdapter);

        if( $throttler->hit($request->ipAddress(), 120, 60) === false ){
            throw new TooManyRequestsHttpException(60, 'Slow it down man!');
        }

        return $next($request);
    }
}
```

Available storage adapters
--------------------------

[](#available-storage-adapters)

The following list of storage adapters are provided "out of the box":

### Redis

[](#redis)

Requires the [Predis](https://github.com/nrk/predis) library available via [predis/predis](https://packagist.org/packages/predis/predis) on Packagist.

```
$redisAdapter = new Throttler\Adapters\Redis(
    new Predis\Client("tcp://localhost:6379")
);

$throttler = new Throttler($redisAdapter);
```

### Database

[](#database)

The database adapter can use any PDO compatible database to persist throttler data. Just add this table to your database:

```
CREATE TABLE throttler
(
    key VARCHAR(64) PRIMARY KEY,
    hits INTEGER UNSIGNED NOT NULL DEFAULT 1,
    expires_at INTEGER UNSIGNED NOT NULL
)
```

```
$databaseAdapter = new Throttler\Adapters\Database(
    new PDO("mysql:dbname=myapp;host=localhost", "username", "password")
);

$throttler = new Throttler($databaseAdapter);
```

You can also customize the columns that the Throttler will use along with garbage collection chance:

- **table** Table name to use. Defaults to **throttler**.
- **key** Key column name. Column type must be a string or varchar. Defaults to **key**.
- **hits** Hits column name. Column type must be an integer. Defaults to **hits**.
- **expires\_at** Expiration column name. Column type must be an integer (UNIX timestamp). Defaults to **expires\_at**.
- **gc\_chance** Percent chance that garbage collection will run. A value less than 1 means it will **never** run. A value greater than 99 means it will run on **every** call. Defaults to **5**.

```
$databaseAdapter = new Throttler\Adapters\Database(
    new PDO("mysql:dbname=myapp;host=localhost", "username", "password"),
    [
        "table" => "limiter",
        "key" => "id",
        "hits" => "value",
        "expires_at" => "ttl",
        "gc_chance" => 20,
    ]
);

$throttler = new Throttler($databaseAdapter);
```

### APCu

[](#apcu)

APCu is an in-memory PHP cache and requires the PECL APCu library available through most Linux package managers.

```
$apcuAdapter = new Throttler\Adapters\Apcu;

$throttler = new Throttler($apcuAdapter);
```

### Memory

[](#memory)

The memory adapter maintains its throttler purely in memory and does not persist its data between HTTP or CLI requets. This adapter is ideal for testing or other special use cases. Only use this adapter if you know what you are doing.

```
$memoryAdapter = new Throttler\Adapters\Memory;

$throttler = new Throttler($memoryAdapter);
```

Custom storage adapters
-----------------------

[](#custom-storage-adapters)

A `Throttler\StorageAdapter` interface is provided so that you may create your own adapters for any persistance engine you want. It must implement two methods:

`get(string $key) : int`

Returns the given key's current counter or 0 if key does not exist.

---

`increment(string $key, int $decay) : int`

Increments the counter for the given key. If key does not exist, it must create it and set its counter to 1 as well as set the counter to expire after **$decay** seconds. Returns the counter value.

```
use Nimbly\Throttler\StorageAdapter;

class MyStorageAdapter implements StorageAdapter
{
    public function get(string $key): int
    {
        // Get $key from storage engine.
    }

    public function increment(string $key, int $decay): int
    {
        // Increment $key on storage engine and return new value.
    }
}
```

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity19

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~270 days

Total

4

Last Release

1943d ago

PHP version history (2 changes)1.0.0PHP ^7

1.1PHP &gt;=7.3 || ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/2fdbed9ace23122d2f6af85ec0ddb4628d499893500f0d1c67742ca3aa33b05d?d=identicon)[brentscheffler](/maintainers/brentscheffler)

---

Top Contributors

[![brentscheffler](https://avatars.githubusercontent.com/u/723164?v=4)](https://github.com/brentscheffler "brentscheffler (30 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/nimbly-throttler/health.svg)

```
[![Health](https://phpackages.com/badges/nimbly-throttler/health.svg)](https://phpackages.com/packages/nimbly-throttler)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
