PHPackages                             zaber-dev/laravel-cooldown - 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. [Database &amp; ORM](/categories/database)
4. /
5. zaber-dev/laravel-cooldown

ActiveLibrary[Database &amp; ORM](/categories/database)

zaber-dev/laravel-cooldown
==========================

Application-level action cooldown management for Laravel with cache and database storage, Eloquent integration, middleware, and a fluent API.

v1.1.1(1mo ago)29939MITPHPPHP ^8.2CI passing

Since Jul 9Pushed 1mo agoCompare

[ Source](https://github.com/zaber-dev/laravel-cooldown)[ Packagist](https://packagist.org/packages/zaber-dev/laravel-cooldown)[ Docs](https://github.com/zaber-dev/laravel-cooldown)[ RSS](/packages/zaber-dev-laravel-cooldown/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (3)Dependencies (7)Versions (4)Used By (0)

 [![Laravel Cooldown Banner](art/header.png)](art/header.png)

Laravel Cooldown
================

[](#laravel-cooldown)

[![Latest Version on Packagist](https://camo.githubusercontent.com/15f915cd8450aeb83b91a752486134b9113370a707316c0b8a3f5a70f2bfd00e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a616265722d6465762f6c61726176656c2d636f6f6c646f776e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/zaber-dev/laravel-cooldown)[![Run Tests](https://camo.githubusercontent.com/a6c9d6270f1f53b8ce3c8c6f269288c2c710ea140f9dde8e9a4ff4f9b8210b93/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7a616265722d6465762f6c61726176656c2d636f6f6c646f776e2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/zaber-dev/laravel-cooldown/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/f8d9f764eb350ff681d2a5cd18b85bc16cae147a96cba1931bd6435f95cbd2ef/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7a616265722d6465762f6c61726176656c2d636f6f6c646f776e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/zaber-dev/laravel-cooldown)[![PHP Version Require](https://camo.githubusercontent.com/cdcabfb96064e3beca1f914f450a61933fd62d30c0a17a5c21a22637358998d7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f7a616265722d6465762f6c61726176656c2d636f6f6c646f776e2f7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/zaber-dev/laravel-cooldown)[![License](https://camo.githubusercontent.com/b2a28d5ea7042b5d237e51c942d7ae1e4f59ff6f9c55f96f82b00c600d36b3b0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7a616265722d6465762f6c61726176656c2d636f6f6c646f776e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/zaber-dev/laravel-cooldown)

**Supports:** Laravel 11, 12 &amp; 13+ • PHP 8.2+ • Redis • Memcached • Database

Laravel Cooldown is a driver-based cooldown management package for Laravel that helps you enforce time-based restrictions on actions, workflows, and endpoints.

Manage cooldowns using cache or database storage, attach them directly to Eloquent models, protect routes with middleware, and extend the package with custom storage drivers—all through a clean, expressive API.

> Unlike Laravel's built-in `RateLimiter`, Laravel Cooldown is designed for persistent, entity-scoped action cooldowns and workflow delays with interchangeable cache and database storage.

---

Quick Example
-------------

[](#quick-example)

```
// Option 1: High-level atomic execution (enforces + locks + sets cooldown on success)
Cooldown::for('send_otp', $user)->block(function () use ($otpService, $user) {
    $otpService->send($user->phone);
}, duration: 120);

// Option 2: Step-by-step enforcement
Cooldown::for('password_reset', $user)->enforce();

// Do work...

Cooldown::for('password_reset', $user)->for(300);
```

---

Documentation
-------------

[](#documentation)

- [Installation](#installation)
- [Configuration](#configuration)
- [Usage Guide](#usage-guide)
- [Agentic Development with Laravel Boost](#agentic-development-with-laravel-boost)
- [LEARN.md](LEARN.md)

---

Common Use Cases
----------------

[](#common-use-cases)

Laravel Cooldown is ideal for:

- Password reset requests
- Email verification
- SMS / OTP sending
- AI prompt generation
- Report exports
- Payment retries
- Promotional rewards
- API actions
- Spam protection
- User workflows

---

Features
--------

[](#features)

- **Multiple Storage Drivers** (Cache &amp; Database): Switch seamlessly between high-performance `cache` stores (Redis, Memcached, Array) and persistent `database` storage with automatic cleanup.
- **Expressive Fluent API**: Chain expressive calls like `Cooldown::for('send_email', $user)->using('database')->for(300)` or enforce limits with `enforce()`.
- **Atomic In-Flight Locking**: Prevent concurrent double-clicks and race conditions using `block()` or the built-in middleware.
- **Native Eloquent Integration**: Attach the `HasCooldowns` trait to any model for scoped action tracking (`$user->cooldown('password_reset')->active()`).
- **Route Middleware**: Protect endpoints automatically using `cooldown:action_name,duration_in_seconds` with automatic HTTP `429` enforcement and `Retry-After` headers.
- **Immutable DTOs**: Work safely with strict `CooldownInfo` Data Transfer Objects returning precision durations (`remainingSeconds()`, `remainingForHumans()`).
- **Prunable Database Storage**: Built-in `Prunable` trait integration ensures expired database records never clutter your database.
- **Custom Driver Extensibility**: Register custom storage drivers on the fly with closure-based creators via `Cooldown::extend()`.

---

Why Laravel Cooldown?
---------------------

[](#why-laravel-cooldown)

While Laravel includes a built-in `RateLimiter` designed primarily for request throttling (e.g., "60 requests per minute"), **Laravel Cooldown** is engineered for temporal action constraints, workflow delays, and entity-scoped cooldowns across multiple storage backends.

FeatureLaravel RateLimiterCustom Cache ChecksLaravel Cooldown**Fluent Builder API** (`Cooldown::for()->until()`)❌❌✅ **Expressive &amp; Clean****First-Class Eloquent Integration** (`$user->cooldown()`)❌❌✅ **Native (`HasCooldowns`)****Driver-Based Architecture** (`cache` &amp; `database`)❌ Cache Only❌ Manual✅ **Both Supported****Atomic In-Flight Locking** (`block()`)❌⚠️ Manual✅ **Built-in****Success-Only Middleware Triggering**❌ (Triggers on 4xx/5xx)❌✅ **Only on 2xx / 3xx****Temporal / Time-Based Delays &amp; Constraints**⚠️ Limited❌ Manual✅ **Subsecond Precision****Immutable DTOs (`CooldownInfo`)**❌❌✅ **Strict (`CarbonImmutable`)****Automatic Database Pruning** (`model:prune`)N/A❌ Manual SQL✅ **Built-in (`Prunable`)****Polymorphic Target Scoping** (Models, Scalars, IPs)❌ Manual Keys❌ Manual Keys✅ **Automatic Key Mapping****Custom Driver Extensibility** (`Cooldown::extend()`)❌❌✅ **Closure / Container****Event Dispatching** (`CooldownInitiated` / `Reset`)❌❌✅ **Configurable Events**---

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

[](#installation)

Ready to get started? Install the package with Composer:

```
composer require zaber-dev/laravel-cooldown
```

Publish the configuration and database migrations:

```
php artisan vendor:publish --provider="ZaberDev\Cooldown\CooldownServiceProvider"
```

Run migrations if you intend to use the `database` driver:

```
php artisan migrate
```

---

Configuration
-------------

[](#configuration)

The configuration file `config/cooldowns.php` allows you to define your default storage driver, driver parameters, and event dispatching behaviors:

```
return [
    /*
    |--------------------------------------------------------------------------
    | Default Cooldown Driver
    |--------------------------------------------------------------------------
    |
    | Supported drivers: "cache", "database"
    |
    */
    'default' => env('COOLDOWN_DRIVER', 'cache'),

    'drivers' => [
        'cache' => [
            'driver' => 'cache',
            'store' => env('COOLDOWN_CACHE_STORE', null),
            'prefix' => 'cooldowns:',
        ],
        'database' => [
            'driver' => 'database',
            'table' => 'cooldowns',
        ],
    ],

    'events' => [
        'dispatch' => true,
    ],
];
```

---

Usage Guide
-----------

[](#usage-guide)

### 1. The Fluent Cooldown API

[](#1-the-fluent-cooldown-api)

The `Cooldown` facade provides an expressive builder interface for setting, checking, enforcing, and resetting cooldowns.

#### Setting a Cooldown

[](#setting-a-cooldown)

```
use ZaberDev\Cooldown\Facades\Cooldown;

// Put a 5-minute cooldown on "export_reports" globally
Cooldown::for('export_reports')->for(300);

// Put a 1-hour cooldown on a specific user
Cooldown::for('send_sms', $user)->for(3600);

// Set expiration using Carbon / DateTimeInterface
Cooldown::for('daily_bonus', $user)->until(now()->endOfDay());
```

#### Checking Cooldown Status

[](#checking-cooldown-status)

```
// Check if an action is currently active (on cooldown)
if (Cooldown::for('send_sms', $user)->active()) {
    $info = Cooldown::for('send_sms', $user)->info();

    echo "Please wait " . $info->remainingForHumans() . " before trying again.";
    echo "Seconds remaining: " . $info->remainingSeconds();
}

// Check if NOT on cooldown
if (Cooldown::for('send_sms', $user)->expired()) {
    // Proceed with action...
}
```

#### Enforcing Cooldowns (`enforce`)

[](#enforcing-cooldowns-enforce)

If you want to automatically halt execution and throw an HTTP `429 Too Many Requests` exception when a cooldown is active or currently locked mid-execution, call `enforce()`:

```
// Throws CooldownActiveException (HTTP 429) if active or mid-flight, automatically attaching 'Retry-After' header
Cooldown::for('login_attempt', $user)->enforce();
```

#### Atomic Block Execution (`block`)

[](#atomic-block-execution-block)

For operations vulnerable to concurrent double-click bursts (e.g., sending SMS or OTPs), use the `block()` helper. `block()` acquires a temporary atomic lock while the callback executes and only starts the cooldown if execution completes successfully:

```
Cooldown::for('send_otp', $user)->block(function () use ($otpService, $user) {
    $otpService->send($user->phone);
}, duration: 120);
```

#### Advanced: Manual In-Flight Locking (`acquireLock`, `releaseLock`, `isLocked`)

[](#advanced-manual-in-flight-locking-acquirelock-releaselock-islocked)

> We strongly recommend using `block()` for most use cases unless your workflow requires fine-grained manual locking across multi-step or asynchronous execution paths.

```
if (! Cooldown::for('process_payment', $order)->acquireLock(10)) {
    throw new \Exception('Payment processing is already mid-flight.');
}

try {
    // Perform payment charge...
} finally {
    Cooldown::for('process_payment', $order)->releaseLock();
}
```

#### Resetting / Clearing Cooldowns

[](#resetting--clearing-cooldowns)

```
// Immediately clear the cooldown for this action/target
Cooldown::for('send_sms', $user)->reset();
```

---

### 2. Eloquent Model Integration (`HasCooldowns`)

[](#2-eloquent-model-integration-hascooldowns)

Add the `HasCooldowns` trait to any Eloquent model to scope cooldowns directly to that entity:

```
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use ZaberDev\Cooldown\HasCooldowns;

class User extends Authenticatable
{
    use HasCooldowns;
}
```

You can now interact directly with your model instance:

```
$user = User::find(1);

// Set a 2-minute cooldown on "update_profile" for this user
$user->cooldown('update_profile')->for(120);

// Check active status
if ($user->cooldown('update_profile')->active()) {
    return response()->json([
        'message' => 'Too many profile updates.'
    ], 429);
}

// Enforce limits and throw 429 exception if active
$user->cooldown('update_profile')->enforce();

// Reset the cooldown
$user->cooldown('update_profile')->reset();
```

#### Polymorphic Database Querying

[](#polymorphic-database-querying)

When using the `database` driver, `HasCooldowns` also exposes a `cooldowns()` polymorphic relationship, allowing direct querying and bulk management:

```
// Get all database cooldown records assigned to this user
$activeCooldowns = $user->cooldowns()->where('expires_at', '>', now())->get();

// Delete all cooldown records for this user
$user->cooldowns()->delete();
```

---

### 3. Route Middleware

[](#3-route-middleware)

Protect routes declaratively without writing boilerplate checks in your controllers using the `CheckCooldown` middleware:

```
use Illuminate\Support\Facades\Route;

// Enforce a 60-second cooldown on form submissions per User / IP address
Route::post('/contact/submit', [ContactController::class, 'submit'])
    ->middleware('cooldown:contact_submit,60');

// Use a specific driver or dynamic action key
Route::post('/api/reports/generate', [ReportController::class, 'generate'])
    ->middleware('cooldown:report_gen,300,database');
```

**How the Middleware Works:**

- Before executing your controller, `CheckCooldown` verifies active status and acquires a temporary atomic in-flight lock across your configured driver to block concurrent double-click bursts (`HTTP 429`).
- When your controller completes successfully (`2xx` or `3xx`), the permanent temporal cooldown is initiated (`for()`). If the controller fails due to validation (`4xx`) or server errors (`5xx`), the temporary lock is released without applying a cooldown so the user can immediately correct their input and retry.

> For an architectural deep dive into check-lock-execute-set mechanics and driver internals, see [LEARN.md](LEARN.md).

---

### 4. Working with Drivers (`using` &amp; `driver`)

[](#4-working-with-drivers-using--driver)

By default, the package uses the driver defined in `config/cooldowns.php`. You can switch drivers on the fly per request or action:

```
// Store transient rate checks in fast cache/Redis
Cooldown::for('api_ping', $ip)->using('cache')->for(30);

// Store billing/audit cooldowns persistently in SQL database
Cooldown::for('billing_charge', $user)->using('database')->for(86400);

// Direct driver instance access
$cacheDriver = Cooldown::driver('cache');
$cacheDriver->put('custom_key', 180);
```

#### Registering Custom Drivers

[](#registering-custom-drivers)

You can extend the `CooldownManager` with your own storage drivers (e.g., DynamoDB, MongoDB) in your `AppServiceProvider`:

```
use ZaberDev\Cooldown\Contracts\CooldownDriverContract;
use ZaberDev\Cooldown\Facades\Cooldown;

public function boot(): void
{
    Cooldown::extend('redis-cluster', function ($app) {
        return new MyRedisClusterCooldownDriver($app['redis']);
    });
}
```

---

### 5. Database Pruning (`Prunable`)

[](#5-database-pruning-prunable)

When using the `database` driver, expired records are automatically marked for pruning via Laravel's `Prunable` trait on the `ZaberDev\Cooldown\Models\Cooldown` model.

To clean up old records automatically, schedule Laravel's `model:prune` command in your `console.php` or `Kernel.php`:

```
use Illuminate\Support\Facades\Schedule;
use ZaberDev\Cooldown\Models\Cooldown;

Schedule::command('model:prune', ['--model' => Cooldown::class])->daily();
```

---

### 6. Events

[](#6-events)

Whenever a cooldown is initiated or cleared, the package dispatches strongly typed events if enabled (`cooldowns.events.dispatch = true`):

- **`ZaberDev\Cooldown\Events\CooldownInitiated`**: Dispatched when `for()` or `until()` creates a cooldown (`$key`, `$expiresAt`, `$action`, `$target`).
- **`ZaberDev\Cooldown\Events\CooldownReset`**: Dispatched when `reset()` clears a cooldown (`$key`, `$action`, `$target`).

You can listen to these in your `EventServiceProvider` for logging, monitoring, or webhook triggers.

---

Agentic Development with Laravel Boost
--------------------------------------

[](#agentic-development-with-laravel-boost)

**Laravel Cooldown** includes built-in AI support and architectural skills engineered for [Laravel Boost](https://github.com/laravel/boost).

When using AI coding assistants (such as Cursor, Claude Code, or GitHub Copilot connected via the Boost MCP server), your AI agent can automatically load specialized design patterns and exact API rules for implementing rate limits and entity-scoped action cooldowns with our package.

### Automatic Skill Installation

[](#automatic-skill-installation)

When Laravel Boost (`laravel/boost`) is installed in your application, our package AI skill is **automatically discovered and published** during package installation and updates (`php artisan boost:install` or `php artisan boost:update`).

If you install `laravel-cooldown` into an existing Boost-enabled project, our service provider also automatically synchronizes the skill directly into your `.ai/skills/laravel-cooldown` directory on boot with zero configuration needed.

### Manual Skill Installation

[](#manual-skill-installation)

If you prefer to install or update the AI skill manually, you can use any of the following commands:

```
# Using Laravel Boost
php artisan boost:add-skill zaber-dev/laravel-cooldown

# Using Vendor Publish
php artisan vendor:publish --tag=cooldowns-skill
```

### What the AI Skill Teaches Your Assistant

[](#what-the-ai-skill-teaches-your-assistant)

By enabling our skill, your AI assistant will strictly follow package conventions, including:

- Utilizing `Cooldown::for('action', $target)->block(...)` for atomic in-flight execution and double-click race condition protection.
- Applying `use ZaberDev\Cooldown\HasCooldowns;` directly to Eloquent models (`$user->cooldown('send_sms')->for('5 minutes')`).
- Selecting the proper storage driver (`cache` for high-throughput transient limits vs `database` for auditability and server-restart persistence).
- Enforcing route middleware (`middleware('cooldown:action,duration')`) that respects controller validation failures cleanly.
- Handling `CooldownActiveException` (`HTTP 429`) and `Retry-After` headers idiomatically.

---

Related Packages
----------------

[](#related-packages)

This package is part of the **[ZaberDev Laravel Ecosystem](https://github.com/zaber-dev/laravel-ecosystem)** (Laravel Productivity Toolkit) — a cohesive suite of high-level application primitives engineered for concurrency, state management, and resource allocation.

Explore the complete directory of packages, detailed use cases, and documentation in our **[Ecosystem Index Hub](https://github.com/zaber-dev/laravel-ecosystem/blob/main/PACKAGES.md)**.

---

Testing &amp; Quality
---------------------

[](#testing--quality)

Run the comprehensive PHPUnit test suite locally:

```
composer test
```

---

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

[](#contributing)

Thank you for considering contributing! Please ensure any pull requests include thorough PHPUnit tests covering unit, feature, and driver integration scenarios.

---

License
-------

[](#license)

The MIT License (MIT). Please see [LICENSE.md](LICENSE.md) for more information.

---

 **Built with ❤️ as part of the ZaberDev Laravel Ecosystem.**

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance90

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

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 ~0 days

Total

3

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4968461fc31f46ebbff1e3f457a4168b4fad50f9700feac218345dc887be56be?d=identicon)[zaber-dev](/maintainers/zaber-dev)

---

Tags

action-cooldownapicachecomposercooldowndatabaseeloquentlaravellaravel-11laravel-12laravel-13laravel-packagemiddlewarephpphp-packagerate-limitrate-limitingredisthrottlethrottlingmiddlewarelaraveldatabaseeloquentlaravel-packagerediscacherate limitthrottlethrottlingrate limitingcooldown

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zaber-dev-laravel-cooldown/health.svg)

```
[![Health](https://phpackages.com/badges/zaber-dev-laravel-cooldown/health.svg)](https://phpackages.com/packages/zaber-dev-laravel-cooldown)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.9M113](/packages/mongodb-laravel-mongodb)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M341](/packages/laravel-ai)[propaganistas/laravel-disposable-email

Disposable email validator

6023.2M7](/packages/propaganistas-laravel-disposable-email)[api-platform/laravel

API Platform support for Laravel

58190.1k21](/packages/api-platform-laravel)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

46273.9k](/packages/harris21-laravel-fuse)

PHPackages © 2026

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