Product Decisions This Supports
- Build vs. buy for the entitlement layer. The core decision this package informs is whether to hand-roll plan/feature/subscription logic. It cleanly separates entitlements (what a user is allowed to do) from billing (how we collect money), which is the right seam for most SaaS architectures. If we're already planning Stripe/Cashier/Paddle for payments, this package occupies a distinct slot beneath them rather than competing.
- Monetization model flexibility. Countable features (tokens, credits, API calls) with auto-reset intervals, uncountable toggles (feature flags), "unlimited" values, and multiple concurrent subscriptions by slug (
main, addon) directly enable pricing decisions: usage-based tiers, credit top-up addons, seat-based plans, and hybrid subscription + metered models. It lets us ship a credits/tokens pricing model without building a metering subsystem.
- Roadmap sequencing. Because there is no admin UI, no HTTP layer, and no API, adopting this creates roadmap work: plan management screens, subscription admin, feature consumption endpoints, and the billing-provider integration. That scope needs to be explicitly allocated — realistically ~50% of total effort — before committing.
- Packaging strategy for multi-tenant or multi-audience products. The subscriber-agnostic
HasSubscriptions trait (polymorphic) means we can attach plans to User, Tenant, or Team without forking. This supports decisions about whether billing lives at the user or account level.
- Internationalization and go-to-market. Translatable plan/feature names (via Spatie) and orderable plans/features mean localized pricing pages and marketing surfaces come nearly free — a real consideration if we launch in multiple markets.
- Billing provider optionality. Meta data on plans and subscriptions (e.g., currency,
price_per_token) plus lifecycle events (SubscriptionRenewed, creation, cancellation) mean the provider decision can be deferred or swapped. This is a genuine hedge: we can pick Stripe now and move to Paddle or in-house invoicing later without rewriting entitlement logic.
When to Consider This Package
Consider it when:
- We're building a Laravel SaaS and need plans, addons, feature gating, and/or credit metering — but are not trying to solve invoicing, tax, or payment capture with it.
- We intend to use Stripe/Cashier, Paddle, or an existing billing system, and just need the entitlement layer above it.
- We need countable features with auto-reset (monthly token allowances, credits) and/or usage split across ordered plans — the differentiated capability that's genuinely annoying to build correctly in-house.
- Multi-subscription-by-slug (a base plan plus addons) is on the roadmap, or likely to be.
- We want localized, orderable plan/feature catalogs for user-facing pricing pages.
- We need the subscriber to be something other than
User (tenant, team, organization).
- We're comfortable owning the UI, API, and admin surface ourselves, and have the design/eng capacity to do so.
Look elsewhere when:
- We need billing, invoicing, dunning, proration billing, or tax handled out of the box. This package explicitly does not do that; Laravel Cashier or a full billing platform is the fit.
- We need a mature, battle-tested dependency with a large ecosystem. At 7 stars, 0 dependents, and a single maintainer, this is bus-factor-1 and unproven at scale — a legitimate reason to prefer a commercial entitlements service or an in-house build if the domain is core to the business.
- Our stack isn't Laravel/PHP (obviously), or we can't tolerate a 1.x API that may shift.
- The product's monetization is simple (one or two fixed plans, no metering) — the abstraction is overkill; a
plan column on the user plus feature flags is cheaper and clearer.
- We already run Laravel Cashier and its
subscriptions table — table-namespace collision risk means we'd need careful migration/alias work, and using two subscription systems side by side invites data-model confusion.
- We require vendor support, SLAs, or an admin UI out of the box.
How to Pitch It (Stakeholders)
To executives — the business case in one paragraph:
lacodix/laravel-plans is a free (MIT), lightweight Laravel package that gives us the pricing and entitlement foundation for a SaaS product — plans, addons, feature toggles, and metered credits — without locking us into any payment provider. It lets us ship usage-based and credit-based pricing models faster than building them, keeps our options open with Stripe, Paddle, or in-house billing, and supports localized plan catalogs for multi-market launches. The trade-offs are honest: it is a small, single-maintainer open-source project (low adoption), and it does not handle billing, invoicing, or admin screens — we build those. So the pitch is "buy the entitlement logic, build the product surface, keep billing optional," not "adopt a billing platform."
To engineering — the technical summary:
- Single
composer require, auto-discovered provider, publishable migrations, one HasSubscriptions trait on the subscriber model. No SDKs, credentials, or external services.
- Owns three concerns cleanly: the plan/feature catalog, the subscription lifecycle (periods, renewals, cancellations, events), and entitlement consumption (countable/uncountable, unlimited, auto-reset, ordered multi-plan consumption).
- Deliberately excludes billing, invoicing, and pricing enforcement — integration is via lifecycle events, so our invoice provider is a listener, not a fork.
- Composes with Spatie packages we likely already use (
laravel-translatable, eloquent-sortable). Polymorphic subscriber supports multi-tenant.
- Risks to accept or mitigate: bus-factor-1 dependency, 1.x API, no production user base to validate edge cases, and potential
subscriptions table collision with Cashier. Recommend wrapping the package behind our own service/interface layer, pinning the version, and budgeting the UI/API work (~half the adoption effort) explicitly.
Recommendation: Pilot it behind an internal abstraction on a low-risk surface (e.g., a new addon or credit-based tier) to validate fit and the maintainer's responsiveness; do not make it load-bearing for core revenue until we've either wrapped it well or confirmed the project's longevity.