PHPackages                             sunspikes/php-ratelimiter - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. sunspikes/php-ratelimiter

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

sunspikes/php-ratelimiter
=========================

A framework agnostic rate limiter for PHP

v2.0(1mo ago)79689.1k↓50.4%14[2 issues](https://github.com/sunspikes/php-ratelimiter/issues)1MITPHPPHP ^8.0

Since Sep 7Pushed 1mo ago4 watchersCompare

[ Source](https://github.com/sunspikes/php-ratelimiter)[ Packagist](https://packagist.org/packages/sunspikes/php-ratelimiter)[ RSS](/packages/sunspikes-php-ratelimiter/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (6)Dependencies (7)Versions (10)Used By (1)

PHP Ratelimiter
===============

[](#php-ratelimiter)

A framework independent, flexible and highly extensible rate limiter for PHP.

[![Latest Stable Version](https://camo.githubusercontent.com/58942e00f189dd3036973786d3b2b9c49c14422a2cf3fdffe2e5afb2c3a0e405/68747470733a2f2f706f7365722e707567782e6f72672f73756e7370696b65732f7068702d726174656c696d697465722f762f737461626c65)](https://packagist.org/packages/sunspikes/php-ratelimiter)[![License](https://camo.githubusercontent.com/be7e824ffd0739df8a98185e0c8d2a9ee0d5028acb13c5b836a4e3d9630af80b/68747470733a2f2f706f7365722e707567782e6f72672f73756e7370696b65732f7068702d726174656c696d697465722f6c6963656e7365)](https://packagist.org/packages/sunspikes/php-ratelimiter)

Requirements
------------

[](#requirements)

- PHP 8.0 or higher
- [desarrolla2/cache](https://github.com/desarrolla2/Cache) ^3.0

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

[](#installation)

```
composer require sunspikes/php-ratelimiter
```

Usage
-----

[](#usage)

### Overview

[](#overview)

```
use Sunspikes\Ratelimit\Cache\Adapter\DesarrollaCacheAdapter;
use Sunspikes\Ratelimit\Cache\Factory\DesarrollaCacheFactory;
use Sunspikes\Ratelimit\RateLimiter;
use Sunspikes\Ratelimit\Throttle\Factory\ThrottlerFactory;
use Sunspikes\Ratelimit\Throttle\Hydrator\HydratorFactory;
use Sunspikes\Ratelimit\Throttle\Settings\ElasticWindowSettings;

// 1. Make a rate limiter with limit 3 attempts in 10 minutes
$cacheAdapter = new DesarrollaCacheAdapter((new DesarrollaCacheFactory())->make());
$settings = new ElasticWindowSettings(3, 600);
$ratelimiter = new RateLimiter(new ThrottlerFactory($cacheAdapter), new HydratorFactory(), $settings);

// 2. Get a throttler for path /login
$loginThrottler = $ratelimiter->get('/login');

// 3. Register a hit
$loginThrottler->hit();

// 4. Check if it reached the limit
if ($loginThrottler->check()) {
    // access permitted
} else {
    // access denied
}

// Or combine steps 3 & 4
if ($loginThrottler->access()) {
    // access permitted
} else {
    // access denied
}

// To get the number of hits
print $loginThrottler->count();
```

### Configuration

[](#configuration)

By default PHP Ratelimiter uses the [desarrolla2 cache adapter](https://github.com/desarrolla2/Cache), with sample configuration in `config/config.php`.

You can configure the drivers in `config.php`, for example to use memcached change the driver to `'memcache'`:

```
return [
    'default_ttl' => 3600,
    'driver'      => 'memcache',
    'memcache' => [
        'servers' => ['localhost'],
    ],
];
```

Supported drivers: `memory`, `file`, `apc`/`apcu`, `memcache`, `redis`, `mysql`/`mysqli`, `mongo`/`mongodb`, `notcache`.

### Extending

[](#extending)

#### Custom Cache Adapters

[](#custom-cache-adapters)

You can use any cache backend by implementing `Sunspikes\Ratelimit\Cache\Adapter\CacheAdapterInterface`:

```
use Sunspikes\Ratelimit\Cache\Adapter\CacheAdapterInterface;
use Sunspikes\Ratelimit\Cache\Exception\ItemNotFoundException;

class SymfonyCacheAdapter implements CacheAdapterInterface
{
    public function __construct(
        private CacheItemPoolInterface $pool
    ) {}

    public function get(string $key): mixed { /* ... */ }
    public function set(string $key, mixed $value, ?int $ttl = null): void { /* ... */ }
    public function delete(string $key): void { /* ... */ }
    public function has(string $key): bool { /* ... */ }
    public function clear(): void { /* ... */ }
}
```

#### Custom Hydrators

[](#custom-hydrators)

You can have custom hydrators by implementing `Sunspikes\Ratelimit\Throttle\Hydrator\DataHydratorInterface`.

For example to use a Symfony Request object for rate limiting:

```
use Sunspikes\Ratelimit\Throttle\Entity\Data;
use Sunspikes\Ratelimit\Throttle\Hydrator\DataHydratorInterface;

class RequestHydrator implements DataHydratorInterface
{
    public function hydrate(mixed $data): Data
    {
        $key = $data->getClientIp() . $data->getPathInfo();

        return new Data($key);
    }
}
```

Then decorate or extend the `HydratorFactory` to recognize your data:

```
use Sunspikes\Ratelimit\Throttle\Hydrator\FactoryInterface;
use Sunspikes\Ratelimit\Throttle\Hydrator\DataHydratorInterface;
use Symfony\Component\HttpFoundation\Request;

class MyHydratorFactory implements FactoryInterface
{
    public function __construct(
        private FactoryInterface $defaultFactory
    ) {}

    public function make(mixed $data): DataHydratorInterface
    {
        if ($data instanceof Request) {
            return new RequestHydrator();
        }

        return $this->defaultFactory->make($data);
    }
}
```

Throttler Types
---------------

[](#throttler-types)

### Elastic Window

[](#elastic-window)

An elastic window throttler will allow X requests in Y seconds. Any further access attempts will be counted, but return false as status. The window is extended with Y seconds on every hit, so there must be no hits during Y seconds for the counter to reset to 0.

See [Overview example](#overview) for instantiation.

### Time-based Throttlers

[](#time-based-throttlers)

The following throttlers use time functions, requiring a different factory for construction:

```
use Sunspikes\Ratelimit\Throttle\Factory\TimeAwareThrottlerFactory;
use Sunspikes\Ratelimit\Time\PhpTimeAdapter;

$cacheAdapter = new DesarrollaCacheAdapter((new DesarrollaCacheFactory())->make());
$timeAdapter = new PhpTimeAdapter();

$throttlerFactory = new TimeAwareThrottlerFactory($cacheAdapter, $timeAdapter);
$hydratorFactory = new HydratorFactory();

// $settings = ...
$ratelimiter = new RateLimiter($throttlerFactory, $hydratorFactory, $settings);
```

#### Fixed Window

[](#fixed-window)

Allows X requests in the Y seconds since the first request. The window does not extend.

```
use Sunspikes\Ratelimit\Throttle\Settings\FixedWindowSettings;

// 120 attempts per minute
$settings = new FixedWindowSettings(120, 60);
```

#### Moving Window

[](#moving-window)

Allows X requests during the previous Y seconds. The window is never extended beyond Y seconds.

```
use Sunspikes\Ratelimit\Throttle\Settings\MovingWindowSettings;

// 120 attempts per minute
$settings = new MovingWindowSettings(120, 60);
```

#### Leaky Bucket

[](#leaky-bucket)

A [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket) throttler allows X requests divided over time Y.

Any access attempts past threshold T (default: 0) will be delayed by Y / (X - T).

`access()` returns false if delayed, `hit()` returns the number of milliseconds waited.

**Note: Time limit for this throttler is in milliseconds, where it is seconds for other throttler types.**

```
use Sunspikes\Ratelimit\Throttle\Settings\LeakyBucketSettings;

// 120 attempts per minute, start delaying after 30 requests
$settings = new LeakyBucketSettings(120, 60000, 30);
```

#### Retrial Queue

[](#retrial-queue)

Wraps another throttler. When a hit would fail on the internal throttler, the request is delayed until the internal throttler has capacity again.

```
use Sunspikes\Ratelimit\Throttle\Settings\RetrialQueueSettings;

// Leaky bucket that delays any overflow
$settings = new RetrialQueueSettings(new LeakyBucketSettings(120, 60000, 120));
```

Author
------

[](#author)

Krishnaprasad MG \[@sunspikes\]

Contributing
------------

[](#contributing)

Please feel free to send pull requests.

License
-------

[](#license)

This is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).

###  Health Score

63

—

FairBetter than 99% of packages

Maintenance91

Actively maintained with recent releases

Popularity51

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 82.1% 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 ~651 days

Recently: every ~895 days

Total

7

Last Release

43d ago

Major Versions

v1.3.0 → v2.02026-05-22

PHP version history (3 changes)v1.0PHP &gt;=5.5

v1.3.0PHP &gt;=7.1

v2.0PHP ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/75611?v=4)[Krishnaprasad MG](/maintainers/sunspikes)[@sunspikes](https://github.com/sunspikes)

---

Top Contributors

[![sunspikes](https://avatars.githubusercontent.com/u/75611?v=4)](https://github.com/sunspikes "sunspikes (55 commits)")[![Feijs](https://avatars.githubusercontent.com/u/12059414?v=4)](https://github.com/Feijs "Feijs (7 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (2 commits)")[![k00ni](https://avatars.githubusercontent.com/u/381727?v=4)](https://github.com/k00ni "k00ni (1 commits)")[![plotbox-io](https://avatars.githubusercontent.com/u/62928171?v=4)](https://github.com/plotbox-io "plotbox-io (1 commits)")[![TomA-R](https://avatars.githubusercontent.com/u/1606901?v=4)](https://github.com/TomA-R "TomA-R (1 commits)")

---

Tags

phprate-limiterthrottlerrate limitthrottlethrottlingratelimitKrishnaprasad MGsunspikesphp-ratelimiter

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sunspikes-php-ratelimiter/health.svg)

```
[![Health](https://phpackages.com/badges/sunspikes-php-ratelimiter/health.svg)](https://phpackages.com/packages/sunspikes-php-ratelimiter)
```

###  Alternatives

[davedevelopment/stiphle

Simple rate limiting/throttling for php

2568.3M9](/packages/davedevelopment-stiphle)[bandwidth-throttle/token-bucket

Implementation of the Token Bucket algorithm.

5132.0M10](/packages/bandwidth-throttle-token-bucket)[graham-campbell/throttle

Throttle Is A Rate Limiter For Laravel

7212.4M11](/packages/graham-campbell-throttle)[hamburgscleanest/guzzle-advanced-throttle

A Guzzle middleware that can throttle requests according to (multiple) defined rules. It is also possible to define a caching strategy, e.g. get response from cache when rate limit is exceeded or always get cached value to spare your rate limits.

13033.4k1](/packages/hamburgscleanest-guzzle-advanced-throttle)[bandwidth-throttle/bandwidth-throttle

Bandwidth throttle at application layer

87147.1k](/packages/bandwidth-throttle-bandwidth-throttle)[hamburgscleanest/laravel-guzzle-throttle

A Laravel wrapper for https://github.com/hamburgscleanest/guzzle-advanced-throttle.

7914.3k](/packages/hamburgscleanest-laravel-guzzle-throttle)

PHPackages © 2026

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