Docs / Plans & billing / Plan limits and quotas

Plan limits and quotas

Seat counts, client caps, feature flags, and what happens when you hit a limit.

Each tier has two kinds of constraints: numeric quotas (max users, max clients) checked when you create a record, and feature flags checked at every request. Both come from config/plans.php.

Numeric quotas

  • User seats. Owners + technicians count together. Seedling = 1, Growth = 10, Estate = unlimited. Enforced in EmployeeController@store: hitting the cap returns the form with an upgrade message.
  • Active clients. Counted as rows in the clients table excluding soft-deleted. Seedling = 100, Growth = 1,000, Estate = unlimited. Enforced in ClientController@store and the bulk CSV import.
  • Crews. Currently advisory — surfaced on pricing, not enforced. Crew counts depend on tech assignments and aren't a hard limit.

Feature flags

These are the per-tier on/off switches that control which routes and nav items light up. The full list is on Plan overview; the most consequential are:

  • Quotes — Growth+
  • Recurring services / subscriptions — Growth+
  • Dispatcher + route optimization — Growth+
  • Custom message templates + unified inbox — Growth+
  • Reviews module — Growth+
  • Audit log — Growth+
  • Multi-language messages — Growth+
  • Reports + charts page — Growth+ (basic dashboard KPIs are on every plan)
  • AI-drafted dunning reminders — Estate only
  • Commission tracking — Estate only
  • API tokens (Sanctum) — Estate only
  • Inbound-email parsing — Estate only
  • White-label branding — Estate only

When you hit a quota

The form rejects the create with an inline error pointing to the upgrade page. No partial state is written. Existing records over the cap (typical when you downgrade) keep working — limits are enforced on creation, not retention.

When you hit a feature gate

Two paths:

  1. Browser: the gated route redirects to /billing/upgrade?reason=<feature_key>. The upgrade page shows a banner like "Quotes is not included on your Seedling plan."
  2. API / JSON: the response is HTTP 402 with body {"error":"plan_upgrade_required","feature":"quotes","feature_label":"Quotes / estimates","current_plan":"seedling"}.
You can preview what a different plan looks like before committing — open /billing/upgrade and use the comparison cards. Hovering a feature you would gain shows a brief description.

Was this article helpful?

Contact support