Share your code editable and funny templates.

Tashil: Subscription Plans, Feature Limits & Usage Tracking For Laravel

Published on October 9, 2026 by

Tashil: Subscription Plans, Feature Limits & Usage Tracking for Laravel

💳 Tashil: Subscription Plans, Feature Limits & Usage Tracking for Laravel

Every SaaS eventually needs the same boring-but-critical machinery: plans, trials, "you've used 4 of 5 uploads", upgrade nudges, failed-payment retries. Tashil is a Laravel package that gives you all of it — without locking you into Stripe Billing or any specific payment gateway.

Think of it as the subscription brain of your app: it owns plans, who is subscribed, what each plan allows, and how much each customer has used. It issues invoices and tracks their state — but it never moves money. Your gateway (Stripe, Paddle, eSewa, whatever you use) stays yours; Tashil just records what happened.

What you'll build: a podcast-hosting SaaS with Hobby and Studio plans, monthly upload limits, a custom-domain toggle, trials, and upgrade nudges — in about 30 minutes.

Prerequisites: a Laravel app, a database, and (optionally) Redis for caching hot counters.


📦 1. Install

composer require foysal50x/tashil
php artisan vendor:publish --tag=tashil-config
php artisan vendor:publish --tag=tashil-migrations
php artisan migrate

👥 2. Make Your Model Subscribable

Any Eloquent model can hold a subscription — User, Team, Organization, a tenant model. Implement the contract and use the trait:

use Foysal50x\Tashil\Contracts\Subscribable;
use Foysal50x\Tashil\Traits\HasSubscriptions;
 
class Team extends Model implements Subscribable
{
use HasSubscriptions;
}

Building for teams instead of users? Tell Tashil how to find "the current subscriber" so Blade directives and middleware resolve the right one:

Tashil::resolveSubscribableUsing(fn () => auth()->user()?->currentTeam);

🧩 3. Define Features — Five Flavors

Features are the things plans grant. Tashil has five types:

  • Boolean — on/off toggles (custom domain, priority support)
  • Limit — counted quotas that reset (uploads per month)
  • Consumable — absolute amounts you report (GB of storage used)
  • Enum — pick-one-of options (support tier: community / priority / dedicated)
  • Metered — pay-per-unit (AI tokens at $0.001 each)
use Foysal50x\Tashil\Facades\Tashil;
use Foysal50x\Tashil\Enums\ResetPeriod;
 
$uploads = Tashil::feature('episode-uploads')
->name('Episode Uploads')
->limit()
->create();
$uploads->update(['reset_period' => ResetPeriod::Monthly]);
 
$customDomain = Tashil::feature('custom-domain')
->name('Custom Domain')
->boolean()
->create();

📋 4. Build a Package

Packages are plans. A fluent builder, with features attached at chosen values:

$hobby = Tashil::package('hobby')
->name('Hobby')
->price(12)
->monthly()
->feature($uploads, value: '4')
->feature($customDomain, value: 'false')
->create();

One comforting detail: if you change a plan later, teams already on it keep the limits they signed up with. Only new subscribers get the new values. No accidental downgrades, no angry emails.


🚀 5. Subscribe — Trials Included

$subscription = Tashil::subscription()
->subscribe($team, $hobby, withTrial: true);

Trials are first-class citizens: isOnTrial() is strict, and converting a trial anchors the first paid period and issues the first invoice. Priced plans subscribe as pending with no access until the first invoice is paid; free plans go straight to active.


🚦 6. Gate Access and Track Usage

This is the money line of the whole package:

if (! $team->useFeature('episode-uploads')) {
return back()->withErrors([
'audio' => "You've used all {$team->featureValue('episode-uploads')} uploads this month.",
]);
}

useFeature() increments the counter and returns false when the limit is reached. The check and the increment happen in one database query — a conditional UPDATE — so two uploads hitting at the same moment can't both sneak past the limit. Race-safe by construction, not by luck.

Blade and routes get helpers too:

@feature('custom-domain')
<x-domain-settings />
@else
<p>Custom domains are available on the Studio plan.</p>
@endfeature
Route::middleware('feature:custom-domain')->group(...);
Route::middleware('plan:studio')->group(...);
Route::middleware('subscribed')->group(...);

And when a team crosses 80% of a limit, Tashil fires a UsageLimitWarning event once per period — the perfect hook for a "you're almost out of uploads, want to upgrade?" email.

Subscription usage flow: plan limits, atomic usage counters, and upgrade nudges

Metered and storage-style features work just as smoothly:

$team->useFeature('ai-tokens', 1500); // metered: units × unit price
$team->reportStorage('storage-gb', 38.5); // absolute: 38.5 GB used

🔄 7. Lifecycle: Cancel, Pause, Switch, Downgrade

$team->cancelSubscription(); // grace cancel — access until period end
$team->pauseSubscription(); // banks remaining time
$team->unpauseSubscription();
$team->switchPlan($studioPlan); // immediate switch
$team->scheduleDowngrade($hobby);// takes effect at period end
$team->changePlan($studioPlan); // in-place change, prorated

Failed payments get a proper dunning flow — Active → PastDue → Suspended → Expired — processed by the tashil:process-dunning command, with automatic recovery when payment lands.


🧾 8. Billing Without the Gateway Lock-In

Tashil's philosophy in one line: it owns the invoice, never the money.

It issues renewal invoices, routes paid invoices by kind (initial → activate, renewal → advance period, lapsed → reactivate), and prorates in-place plan changes. Your gateway integration charges the card and tells Tashil the invoice was paid. Every state change lands in an immutable, append-only event log with idempotency keys — an audit trail you can actually trust.


📊 9. Analytics Included

MRR, churn, trial conversion, and per-package breakdowns come out of the box — the numbers a SaaS founder checks every morning, without wiring up a separate analytics pipeline.


🎯 Final Thoughts

Tashil is the rare package that treats SaaS pricing as a product feature, not a billing afterthought. Plans as code, race-safe usage counters, trials, dunning, invoices, analytics — and your payment gateway stays your choice.

If you're building a SaaS in Laravel, this one deserves a weekend spike. What would your first metered feature be? Drop a comment below. 👇


Sources:

Dinesh Uprety

Senior Software Engineer • Writer @ Laranepal • PHP, Laravel, Livewire, TailwindCSS & VueJS • CEO @ Laranepal & Founder @ laracodesnap

Filed in:

Discussion

Login or register to comment or ask questions

No comments yet

Be the first to share your thoughts or ask a question.

Join the conversation

Sign in to share your thoughts with the community.

SPONSORED
Codesnap

Codesnap

Share your code editable and funny templates.