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 Plans Laravel Package

lacodix/laravel-plans

Manage SaaS plans and addons with subscriptions, billing intervals, and countable or unlimited features like credits and tokens that auto-reset. Consume feature usage across plans in order, with translations, sorting, and metadata. No billing included.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • The package owns exactly one bounded context: the entitlement and subscription-state layer. It knows plans, addons, features, subscription periods, renewals, cancellations, and feature consumption. It explicitly does not know invoices, payments, tax, or dunning. For a TPM this is the single most important architectural fact: this is a component that sits under Stripe/Cashier/Paddle, not a replacement for them. If a stakeholder reads "manages subscriptions" and assumes it replaces our billing provider, the project is scoped wrong from day one and needs correcting in the kickoff.
  • The trait-based subscriber model (HasSubscriptions on any Eloquent model, polymorphic relation) means the same primitives serve User, Team, or Tenant. If the roadmap includes seat-based or workspace-based subscription models, we do not pay a second integration cost later. If we are single-user SaaS only, that generality is free but unused.
  • The genuinely differentiated capability is ordered, multi-plan consumption: a subscriber holds a main plan and one or more addon plans, and usage drains feature allocations in subscription order until buckets are exhausted. Hand-rolling this is where most in-house entitlement systems accumulate subtle bugs — partial consumption, reset boundaries, "unlimited" sentinels. Buying this is the strongest argument for adoption.
  • Composable by design with Spatie packages we plausibly already run (laravel-translatable for plan/feature names, eloquent-sortable for display and consumption ordering). No exotic dependencies, no proprietary runtime, no queue worker assumptions.

Integration feasibility

  • Lowest-friction integration tier: composer require, auto-discovered provider, published migrations, one trait on one model. No credentials, no external service, no webhook endpoint, no outbound network calls. A single engineer can stand up a working sandbox in under a day.
  • The package ships zero HTTP surface. No admin UI, no plan-editing screens, no checkout flow, no customer-facing subscription page, no API. All of that is our build. A realistic effort split is roughly 20–30% package integration and 70–80% product surface around it. Any estimate that treats composer require as the milestone is off by an order of magnitude.
  • The event seam (SubscriptionRenewed, plus subscription-created and plan-change events) is the integration contract with our invoice provider. That means billing coupling is an event listener, not a fork of the package — good for both upgrade safety and for swapping providers later.
  • The price column plus effectiveMeta() / effectivePrice() and isInTrial() give us enough to display pricing and proration, and meta gives us a place to stash currency or provider price IDs. It does not compute money correctly for tax or currency conversion. Treat every monetary field as presentation and routing data, with the provider as the source of truth.

Technical risk

  • Adoption risk dominates everything else. 7 stars, 0 dependents, single maintainer, 1.x API, first release measured in months not years. There is no visible production user base to have shaken out edge cases in proration boundaries, timezone handling of reset intervals, or concurrency during consumption. We would be one of the earliest serious adopters, which means we absorb the cost of being the de facto QA function.
  • Bus factor of one. The changelog is overwhelmingly one contributor. Recent releases are small, competent, feature-scoped (Laravel 12 then 13 support, effectiveMeta, isInTrial, effective price, force renew) — a good signal that the maintainer is active and responsive. But there is no foundation, no second maintainer, no commercial support contract, no LTS commitment. Continuity planning is mandatory, not optional.
  • Schema namespace collision. The package publishes plans, features, subscriptions, and pivot tables. Laravel Cashier ships its own subscriptions table. Running both in one database requires renaming one side or isolating schemas. This is a real, concrete integration defect that surfaces in migrations and in every query that touches subscriptions. It must be resolved in design, not discovered in staging.
  • Consumption correctness is the highest-severity unknown. "Consume features, split usage across plans in order" involves read-modify-write on counters. Under concurrency (two requests burning tokens simultaneously) this is a race unless the package uses locking or atomic decrements. The README does not say. We must verify this ourselves before it gates a paid feature — an over-consumed credit bucket is a revenue leak, and an under-consumed one is a support ticket.
  • Versioning posture. Pre-2.0 with a small audience means breaking changes are plausible even inside 1.x. Pinning to ~1.5 and reading the changelog on every bump is required hygiene, not paranoia.
  • License is clean. MIT, no copyleft contamination, no commercial terms to negotiate. One genuine risk removed.

Key questions to resolve before committing

  1. Does feature consumption use database transactions and row locking, or is it a naive read-modify-write? This determines whether we can put it on a hot path.
  2. How are reset intervals anchored — subscription start date, calendar boundary, or timezone of the subscriber? What happens on DST transitions and month-end (Jan 31 → Feb 28)?
  3. What is the concrete plan for the subscriptions table collision if Cashier is present or planned?
  4. Is the maintainer open to a support arrangement, or do we need a fork-with-upstream discipline from day one?
  5. Which features are metered in our product, and can we tolerate a reset/consumption bug in each? Classify by blast radius before integration, not after.
  6. What is the exit cost? Can we swap in a fork, an internal implementation, or a commercial entitlement service without rewriting the product surface?

Integration Approach

Stack fit

  • Laravel-native and version-aligned: the release history shows explicit Laravel 12 and 13 support, indicating the maintainer tracks framework releases. This package is only viable inside a conventional Laravel monolith or a Laravel service — it is not a polyglot or framework-agnostic component, and it should not be proposed to a non-Laravel service as a shared entitlement layer.
  • It assumes relational storage with transactions. That is a fine fit for MySQL/Postgres; it is a warning sign if any part of our stack is on a storage engine or sharding model that weakens transactional guarantees around counters.
  • It slots in cleanly beneath an existing Cashier/Paddle/Stripe integration because it never speaks to those systems. The intended topology is: provider handles money → provider webhook updates our subscription record → laravel-plans holds entitlement state → application code asks "does this subscriber have feature X, how much remains, consume N."

Migration path

  • Recommended posture: net-new surface only. Do not migrate existing paid customers onto this package as a first step. Stand it up alongside the current entitlement logic, run it in shadow mode for a cohort, and cut over per-feature.
  • Concretely: (a) install and publish migrations into a clean schema, resolving the subscriptions name collision up front by configuring table prefixes; (b) seed the plan/feature catalog to mirror current production plans, keeping slugs as the stable application-facing identifiers; (c) wire event listeners that generate no invoices yet, only log, so we validate the renewal event fires where we expect; (d) build a read-only comparison job that evaluates both old and new entitlement checks for real traffic and reports divergence; (e) flip consumers of entitlement checks feature by feature.
  • Keep all application code referencing plans and features by slug, never by ID. The README states slugs are the app-facing identity; honoring that gives us a cheap rebuild path if the catalog has to be reseeded from a different source.
  • Keep monetary state out of the package where possible. Store provider price IDs and currency in meta, and treat the price column as display-only unless we have deliberately decided otherwise.

Compatibility

  • Two compatibility axes to test explicitly, not assume: Laravel version (pin to the release that shipped support for our target major, and re-verify on each framework upgrade) and database engine plus isolation level (consumption correctness under concurrency varies).
  • If Cashier is present or planned, resolve the table collision in the design doc. Options: prefix the package's tables, isolate it in a separate schema/database, or rename Cashier's. Each has different query and migration consequences; pick deliberately.
  • Translatability via laravel-translatable is a soft coupling: if we already use it, plan and feature naming is a non-issue; if we do not, either adopt it or store single-locale names. Determine this before the catalog seed, because it affects the shape of production data.
  • Pin the dependency and treat every version bump as a review gate until we have either a support relationship or a fork we control.

Sequencing

  1. Spike (days, not weeks). Build a throwaway sandbox that answers the concurrency and reset-boundary questions. This is the go/no-go gate and it is cheap. Do not skip it to hit a date.
  2. Decision record. Document the topology (provider → subscription → entitlement → app), the table-collision resolution, the consumption guarantee we are relying on, and the exit plan. The exit plan is what makes the rest of the decision defensible to reviewers.
  3. Catalog design. Model plans, addons, features (countable vs uncountable), values, and reset intervals. This is product work, not engineering work — get product and finance to sign off on every metered feature and its reset semantics before code.
  4. Foundation build. Models published/configured, trait applied, event listeners wired to the billing provider in log-only mode.
  5. Shadow evaluation. Dual-evaluate entitlement checks against the legacy path, measure divergence to zero.
  6. Cutover by feature, ordered by lowest blast radius first: cosmetic/uncountable toggles, then soft limits, then hard metered credits.
  7. Admin surface. Internal-only plan and subscription management first; customer-facing screens last, since they are pure UI on a settled model.
  8. Hardening. Concurrency tests, reset-boundary tests around month-end and DST, and an alert on consumption anomalies.

Operational Impact

Maintenance

  • Low ongoing maintenance of the package, high ongoing maintenance of our surface. The dependency is small and stable; the admin UI, checkout flow, catalog editing, and customer-facing subscription screens are all ours and all need owners.
  • Real recurring cost is upgrade diligence: every Laravel major and every package minor needs a review, a changelog read, and a test pass. Budget a small but permanent allocation rather than assuming this is a one-time integration.
  • Because we would be an early adopter, we should expect to author tests that upstream lacks — particularly around consumption concurrency and reset boundaries — and to consider contributing them. Contributing is also the cheapest way to build influence over a bus-factor-1 dependency.

Support

  • No commercial support exists. No vendor, no SLA, no escalation path. Issues are answered by whoever is available. Our mitigation is not hope; it is a documented policy: internal owner named, upstream issue triage expectations set (business days, not hours), and a pre-approved fallback of vendoring the package into our repo if upstream goes quiet or a fix is needed urgently.
  • Establish a fork posture now, before it is needed: know whether we can vendor, patch, and maintain. Doing this under incident pressure is much worse than doing it in a design doc.
  • Maintain a written record of any local patches so a future upstream sync is mechanical rather than archaeological.

Scaling

  • Subscription and feature tables are small: rows scale with subscribers and plans, not with traffic. That is comfortable for a long time on a conventional database.
  • The scaling pressure is on consumption, which is a write per metered action on a potentially hot row. Two things to watch: lock contention on a subscriber's feature-usage rows under high request rates, and the cost of the ordered multi-plan split (a consume may scan several buckets). Both are manageable, but they are architectural: design high-volume metering paths to batch or queue consumption, and do not put a synchronous multi-bucket consume in the critical path of every API request without measuring it first.
  • Renewal processing should be a scheduled job with idempotency, not a best-effort loop. The aggregation and force-renew features suggest the maintainer has thought about this; confirm before relying on it.
  • Read paths (does this user have feature X?) should be cached per subscriber with invalidation on subscription change and on reset. This is our code, not the package's, and it is where scale is actually won.

Failure modes

  • Silent over-consumption (race condition on counters) — revenue leakage, invisible until reconciliation. Mitigation: verify locking in the spike; add a reconciliation report comparing consumed totals against billed usage.
  • Silent under-consumption or premature reset — customers hit limits they already paid for; loud, embarrassing, support-heavy. Mitigation: deterministic reset-boundary tests and an alert on unexpected reset volume.
  • Subscription state drift from the billing provider — the package's state and the provider's state disagree after a missed or duplicated webhook. This is the classic failure of any entitlement layer. Mitigation: make the provider authoritative, make webhook handling idempotent, and run a periodic reconciliation job rather than trusting either side blindly.
  • Table collision with Cashier — migration failures, or worse, queries silently hitting the wrong subscriptions table. Mitigation: resolve at design time and assert the table name in a test.
  • Abandonment — the maintainer disappears, or 2.0 diverges from our needs. Mitigation: vendoring readiness, pinned versions, and a small enough codebase to own if required.
  • Breaking change inside 1.x — a patch bump silently alters consumption or reset behavior. Mitigation: pin, read changelogs, run a behavioral test suite built around our product's invariants rather than the package's.

Ramp-up

  • Individual engineers: very fast. If the team knows Laravel, a developer is productive against the API in a day or two; the README and the documentation site with worked use cases carry most of the load.
  • Team-level: the hard part is shared mental model, not syntax. Everyone touching entitlement logic needs the same understanding of what "unlimited" means as a sentinel, how ordered multi-plan consumption splits a single purchase, what reset intervals do at boundaries, and above all that this package is not the source of truth for money. Those are the misunderstandings that produce bugs.
  • Recommended onboarding artifacts, all of which we must write ourselves: a one-page entitlement topology diagram, a decision record capturing the concurrency and collision resolutions, a runbook for subscription/webhook reconciliation, and a test suite that encodes our product's entitlement invariants. That test suite is the single highest-leverage onboarding asset — it teaches the model faster than any prose and it protects us through upgrades.
  • Estimate the overall shape honestly: package integration is a small fraction of the effort; catalog design, admin surface, billing-provider event wiring, reconciliation, and hardening are the bulk. Plan and staff accordingly, and treat the early spike as a mandatory gate rather than a formality — a package with 7 stars and 0 dependents earns adoption through verification, not reputation.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin