Laravel Quota: Usage Budgets for Calendar Periods | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. [Laravel](https://www.msaied.com/public/articles?category=laravel)
6. /
7. Laravel Quota: Enforce Usage Budgets for Calendar Periods in Laravel

   [Laravel](https://www.msaied.com/public/articles?category=laravel) [Composer Pacakge](https://www.msaied.com/public/articles?category=composer-pacakge) 

 Laravel Quota: Enforce Usage Budgets for Calendar Periods in Laravel
=====================================================================

 Laravel Quota is a package that tracks and enforces cumulative usage limits—like 50 PDF exports per month or 1,000 API calls per day—against calendar-aligned periods, with cache or database backends.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 14 Jul 2026 · Updated 14 Jul 2026 · 4 min read

ShareCopy linkCopied

 ![Laravel Quota: Enforce Usage Budgets for Calendar Periods in Laravel](https://cdn.msaied.com/424/b6dac94325ccc99dff6556fefb82969d.png) 

  On this page +1. [What Is Laravel Quota?](#what-is-laravel-quota)
2. [Key Features](#key-features)
3. [The Fluent API](#the-fluent-api)
4. [Quotas on Eloquent Models](#quotas-on-eloquent-models)
5. [Route Middleware](#route-middleware)
6. [Storage Backends](#storage-backends)
7. [Installation](#installation)
8. [Real Takeaways](#real-takeaways)

 What Is Laravel Quota?
----------------------

[Laravel Quota](https://github.com/zaber-dev/laravel-quota) (`zaber-dev/laravel-quota`) is a package for tracking and enforcing **cumulative usage limits** that reset on calendar boundaries. Think 50 PDF exports per month, 1,000 API queries per day, or a pool of AI credits per billing cycle.

It solves a different problem than Laravel's built-in `RateLimiter`. Instead of throttling bursts in a sliding window, it counts consumption against a named budget that resets at a predictable calendar boundary—and it can persist that count in the database rather than only in the cache.

Key Features
------------

- Calendar-aligned periods: `perMinute()`, `perHour()`, `perDay()`, `perWeek()`, `perMonth()`, `perYear()`, or a custom `period($start, $end)`
- A `HasQuotas` Eloquent trait to attach quotas directly to any model
- Route middleware (`quota:exports,50,month`) that only consumes the budget on a successful 2xx/3xx response
- Switchable **cache** or **database** backends, configurable per call
- Atomic consumption via `block()` to prevent double-spend under concurrency
- Hard enforcement via `enforce()`, which throws an HTTP 429 when the budget is exhausted

The Fluent API
--------------

A quota is a named counter scoped to an owner, with a limit and a period:

```php
use ZaberDev\Quota\Facades\Quota;

$builder = Quota::for('api_queries', $user)
    ->limit(1000)
    ->perDay();

$builder->used();
$builder->remaining();
$builder->isExceeded();
$builder->hasCapacity(10);

$info = $builder->consume(5);

```

To fail hard instead of branching on the result, call `enforce()`:

```php
Quota::for('api_queries', $user)->limit(1000)->perDay()->enforce();

```

For work where a double-spend matters, `block()` wraps the callback in a lock:

```php
Quota::for('pdf_generation', $user)
    ->limit(50)
    ->perMonth()
    ->block(function () use ($pdfService) {
        $pdfService->generate();
    }, amount: 1, lockSeconds: 30);

```

Quotas on Eloquent Models
-------------------------

Add the `HasQuotas` trait to any model and the same builder is available directly on the instance:

```php
use ZaberDev\Quota\HasQuotas;

class User extends Authenticatable
{
    use HasQuotas;
}

$user->quota('pdf_exports')->limit(25)->perMonth()->consume();
$user->quota('pdf_exports')->limit(25)->perMonth()->remaining();

```

With the database backend, quota records are polymorphic, so you can query them like any other relation:

```php
$activeQuotas = $user->quotas()
    ->where('period_end', '>', now())
    ->get();

```

Route Middleware
----------------

Apply quota enforcement directly to routes with the `quota` middleware:

```php
Route::post('/exports/generate', [ExportController::class, 'store'])
    ->middleware('quota:exports,50,month');

Route::post('/api/v1/query', [ApiController::class, 'query'])
    ->middleware('quota:api_query,1000,day,database');

```

Capacity is checked before the route runs, but the quota is only consumed when the response is 2xx or 3xx. A request that errors or fails validation costs the user nothing.

Storage Backends
----------------

The default driver is `cache` (Redis, Memcached, or any configured store). Switch to `database` when the count is tied to billing and must survive a cache flush:

```php
Quota::for('api_ping', $ip)->using('cache')->limit(5000)->perDay()->consume();
Quota::for('monthly_exports', $user)->using('database')->limit(50)->perMonth()->consume();

```

Expired database rows can be pruned on a schedule:

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

```

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

Requires PHP 8.2 and supports Laravel 11, 12, and 13:

```bash
composer require zaber-dev/laravel-quota
php artisan vendor:publish --provider="ZaberDev\Quota\QuotaServiceProvider"
php artisan migrate

```

Real Takeaways
--------------

- Laravel Quota is a **calendar-reset** budget system, not a sliding-window rate limiter.
- The `enforce()` method returns an HTTP 429 automatically—no manual branching needed.
- Use `block()` for atomic consumption when concurrent requests could both pass the capacity check.
- The **database backend** is the right choice for billing-critical counters that can't be lost on a cache flush.
- Route middleware only charges the budget on successful responses, protecting users from being penalized for server errors.
- Custom backends can be registered via `Quota::extend()` in a service provider.

---

*Source: [Laravel Quota: Usage Budgets for Calendar Periods — Laravel News](https://laravel-news.com/laravel-quota-usage-budgets-for-calendar-periods)*

- [Laravel](https://www.msaied.com/public/articles?search=Laravel)
- [Packages](https://www.msaied.com/public/articles?search=Packages)
- [Rate Limiting](https://www.msaied.com/public/articles?search=Rate%20Limiting)
- [Usage Quota](https://www.msaied.com/public/articles?search=Usage%20Quota)
- [API](https://www.msaied.com/public/articles?search=API)

 Frequently asked questions 
---------------------------

  How is Laravel Quota different from Laravel's built-in RateLimiter?Laravel's RateLimiter throttles bursts of traffic using a sliding time window and is typically backed by cache only. Laravel Quota counts cumulative consumption against a named budget that resets on a fixed calendar boundary (e.g., the start of a month), and it can persist counts in the database so they survive cache flushes—making it suitable for billing-tied limits.

   Does the route middleware charge the quota if the request fails?No. The middleware checks capacity before the route runs but only consumes the quota when the response returns a 2xx or 3xx status code. Requests that result in a 4xx or 5xx response do not count against the user's budget.

   When should I use the database backend instead of the cache backend?Use the database backend when the quota count is tied to billing or any business-critical limit that must not be lost if the cache is flushed or expires. The cache backend is fine for soft limits where occasional resets are acceptable.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articlePostgreSQL Full-Text Search in Laravel: Indexes, ts\_rank, and Weighted Queries](https://www.msaied.com/public/articles/postgresql-full-text-search-in-laravel-indexes-ts-rank-and-weighted-queries) [Next articleFilament v4 Schema-Based Forms, Infolists, and the Unified Schema API](https://www.msaied.com/public/articles/filament-v4-schema-based-forms-infolists-and-the-unified-schema-api-3)  

   On this page
-------------

1. [What Is Laravel Quota?](#what-is-laravel-quota)
2. [Key Features](#key-features)
3. [The Fluent API](#the-fluent-api)
4. [Quotas on Eloquent Models](#quotas-on-eloquent-models)
5. [Route Middleware](#route-middleware)
6. [Storage Backends](#storage-backends)
7. [Installation](#installation)
8. [Real Takeaways](#real-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
