Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Quotas Laravel Package

vimatech/laravel-quotas

Laravel Quotas lets you define and enforce usage limits in your Laravel app, tracking consumption against configurable quotas and checking whether users, tenants, or features are within their allowed limits.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its config/migrations before writing any application code:

composer require vimatech/laravel-quotas
php artisan vendor:publish --provider="Vimatech\Quotas\QuotasServiceProvider"
php artisan migrate

Open the published config/quotas.php first — this is where plan definitions, entitlement keys, and reset behaviour normally live. Read the migration stubs second: they tell you whether usage is stored per-account in a table, in cache, or derived, which determines how you reason about consistency later.

Add the package's trait to your billable model (usually User, sometimes Team):

use Vimatech\Quotas\Concerns\HasQuotas;

class Team extends Model
{
    use HasQuotas;
}

The mental model to adopt on day one: Cashier owns what plan you're on; this package owns what that plan allows and how much you've used. Keep those responsibilities separate in your head and in your code.

Your first use case should be the smallest one that exercises both halves — a boolean feature gate plus one metered counter:

if (! $team->hasFeature('api_access')) {
    abort(403);
}

$team->consumeQuota('api_calls', 1);

Verify the exact method names against the README/source before committing; with a package this young, treat the public API as something to confirm rather than assume.

Implementation Patterns

Map plans in one place. Resist scattering if ($team->plan === 'pro') checks. Define a single plan → entitlements map (config or a plans table seeded from config) and let the package resolve it. When a plan changes, you edit one array, not forty controllers.

Sync plan on Cashier webhooks. The most common integration point is CustomerSubscriptionUpdated / Created / Deleted. In those listeners, translate the Cashier price/plan into the package's plan key and persist it. Don't let the two systems drift — a cancelled subscription that leaves quotas at "pro" is a revenue leak and a support ticket.

Gate HTTP at the middleware/policy layer, gate UI in Blade. Use the package's middleware (or a thin custom one wrapping hasFeature) on route groups, and a Blade directive or @if for showing/hiding menu items. Never rely on UI hiding alone; the API must enforce.

Route::middleware(['auth', 'quota.feature:api_access'])->group(function () {
    Route::post('/api/things', ...);
});

Meter atomically. For counters, always check-and-increment in one operation. If the package exposes consumeQuota, prefer it over remaining() > 0 followed by a separate write — that pattern races under concurrency and lets you blow through limits. If you need multiple units per request, consume in a single call, not a loop.

Consume at the boundary, not in the domain. Call consumeQuota in a controller, job middleware, or listener after validation but before the expensive work. Don't sprinkle it through service classes; it becomes impossible to reason about what a "unit" is.

Handle the reset cycle. Most quota packages support daily/monthly windows. If resets are scheduled, confirm the command is in Kernel::schedule() (or Laravel 11's routes/console.php). If resets are lazy (computed from a period start timestamp), you get correctness for free but must be careful with timezone boundaries — decide whether "monthly" means UTC or the account's timezone and be consistent.

Test with time travel and fakes. Freeze time at a period boundary and assert the counter resets. Assert that a downgrade immediately reduces entitlements — that's the behaviour most likely to break and least likely to be covered.

Gotchas and Tips

Race conditions are the main correctness risk. Cache- or column-backed counters without atomic increments will over-consume under load. Audit the implementation (read the source — it's a small package) and, if needed, wrap consumption in Cache::lock() or a DB transaction with lockForUpdate. This is the first thing to load-test.

Cache invalidation on plan change. Plans are frequently cached for performance. Any upgrade/downgrade must explicitly bust that cache, or users who just paid will still see free-tier limits. Add an assertion for this in your webhook tests.

Don't duplicate billing state. It's tempting to copy ends_at, trial status, etc. into your quota tables. Don't. Resolve plan from Cashier at read time (or cache it with a short TTL) so a failed webhook can't leave you with two disagreeing truths.

Middleware ordering matters. A quota middleware that runs before auth has no user to check. Register it after auth/session middleware, and make sure it returns JSON 429/403 for API routes and redirects for web routes — or you'll see HTML error pages in API clients.

Config caching. If entitlements live in config/quotas.php, remember php artisan config:cache in deploy. Changes to plan limits won't apply until the cache is rebuilt. If ops needs to change limits without a deploy, move definitions into the database early rather than fighting this later.

Low-maturity signals — plan accordingly. One star and zero dependents means limited real-world hardening. Pin an exact version in composer.json ("vimatech/laravel-quotas": "1.x" with a lockfile commit), read the diff before composer update, and write your own integration tests around the behaviours you depend on. If you find a bug, a fork or a thin wrapper is a realistic fallback.

Extension points to look for. The useful ones in packages like this are usually: a custom plan resolver (so you can derive plan from Cashier however you like), events emitted on quota exhaustion (hook your alerting/upgrade prompts), and overridable config for the usage store. If the package doesn't document these, check whether the service container bindings are swappable before committing to it.

Watch overage semantics. Decide explicitly what happens past the limit: hard 429, soft warning with overage billing, or silent truncation. Whatever you choose, make the error message actionable ("Upgrade to Pro for 10,000 more calls this month") — quotas exist to drive conversion, not just to block.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log