saas-entitlements-and-plan-gating
Use when designing the entitlements engine that enforces what each plan/tier/tenant can do — feature flags vs entitlements distinction, limits enforcement (seats, API calls, storage, projects, AI tokens), gate placement (UI, API, worker), upgrade-discovery UX, override mechanisms for enterprise contracts, and the runtime that resolves "can this tenant do X right now?" in a few milliseconds.
Best use case
saas-entitlements-and-plan-gating is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when designing the entitlements engine that enforces what each plan/tier/tenant can do — feature flags vs entitlements distinction, limits enforcement (seats, API calls, storage, projects, AI tokens), gate placement (UI, API, worker), upgrade-discovery UX, override mechanisms for enterprise contracts, and the runtime that resolves "can this tenant do X right now?" in a few milliseconds.
Teams using saas-entitlements-and-plan-gating should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/saas-entitlements-and-plan-gating/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How saas-entitlements-and-plan-gating Compares
| Feature / Agent | saas-entitlements-and-plan-gating | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when designing the entitlements engine that enforces what each plan/tier/tenant can do — feature flags vs entitlements distinction, limits enforcement (seats, API calls, storage, projects, AI tokens), gate placement (UI, API, worker), upgrade-discovery UX, override mechanisms for enterprise contracts, and the runtime that resolves "can this tenant do X right now?" in a few milliseconds.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# SaaS Entitlements and Plan Gating
Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.
<!-- dual-compat-start -->
## Use When
- Designing the runtime that answers "what is this tenant allowed to do?" — every gated feature, every limit-checked action, every plan-tied capability.
- Replacing scattered `if tenant.plan == 'pro'` checks with a single entitlements service.
- Designing the data model for plans, features, limits, overrides, and add-ons.
- Supporting enterprise custom-contract overrides without forking the codebase.
- Pairing in-product upgrade prompts (PLG) with the gate runtime so users hit a wall *and* see the path forward.
- Coordinating entitlements with feature flags (distinct concerns; they overlap dangerously if confused).
## Do Not Use When
- The task is Stripe Billing primitives (Plan / Price / Subscription / Trial) — use `subscription-billing`. This skill consumes those primitives.
- The task is experimentation feature flags (A/B tests, gradual rollout) — feature flags ≠ entitlements; see §3.
- The task is per-tenant data isolation — use `multi-tenant-saas-architecture`.
- The task is enterprise SSO/SCIM — use `saas-sso-scim-enterprise-auth`.
## Required Inputs
- Plan catalogue (from `subscription-billing`): tier names, features per tier, limits per tier.
- Pricing model decisions (per-seat, usage-based, hybrid) from product.
- List of features to gate + list of limits to enforce.
- Override policy: how enterprise contracts customise entitlements without code changes.
## Workflow
1. Read this `SKILL.md` end-to-end.
2. Distinguish **entitlements** (what plan allows) from **feature flags** (rollout/experimentation) — §3.
3. Design the entitlements data model (§4) — plans, features, limits, overrides.
4. Pick the resolution strategy (§5) — pre-resolved on JWT vs runtime lookup vs hybrid.
5. Place the gates (§6) — UI hint, API enforce, worker enforce.
6. Wire the upgrade-discovery UX (§7) — the gate is also a sales surface.
7. Build the override mechanism (§8) for enterprise contracts.
8. Instrument hits + denials (§9) for PLG analytics.
## Quality Standards
- Entitlements resolution < 5ms p99 on the hot path (API request).
- Single source of truth for "which plan has what" — never duplicate in UI code and API code.
- Every denied action emits an event (for PQL scoring + upgrade prompts).
- Overrides logged in the audit log with actor + reason.
- Limit enforcement is **atomic with the action** — checking the limit and then performing the action races; use SELECT FOR UPDATE / Redis atomic counters / DB constraints.
## Anti-Patterns
- `if (user.plan == 'pro') { … }` scattered across the codebase. Fix: single resolver.
- Entitlements stored only in the front-end (the gate is bypassable). Fix: server-side enforcement is primary; UI mirrors.
- Counting limits via SELECT then INSERT (race condition). Fix: atomic counter or DB unique constraint per period.
- Feature flags and entitlements implemented in the same code path (a feature toggle ends up gating purchases). Fix: separate runtimes.
- Hard-coding "Enterprise" overrides as `if tenant.id == 12345` branches in the code. Fix: data-driven override table.
- No upgrade prompt when a gate denies (user hits a wall, doesn't know why). Fix: every denial response carries `upgrade_url` + reason.
## Outputs
- Plan × feature × limit catalogue (single source of truth).
- Entitlements resolver service + API.
- Gate placement map (UI / API / worker).
- Override schema and admin tool.
- Denial-event analytics dashboard (PQL surface).
## Evidence Produced
| Category | Artifact | Format | Example |
|----------|----------|--------|---------|
| Architecture | Entitlements model spec | Markdown doc | `docs/saas/entitlements-model.md` |
| Release evidence | Plan × Feature × Limit matrix | Markdown table | `docs/saas/plan-feature-matrix.md` |
| Operability | Gate-denial analytics dashboard | Dashboard link | `docs/saas/gate-denials-dashboard.md` |
## References
- `references/entitlements-vs-feature-flags.md` — when each applies; how they coexist.
- `references/limit-enforcement-patterns.md` — atomic counters, period rollover, distributed quotas.
- `references/enterprise-override-model.md` — data-driven overrides for custom contracts.
- Companion: `subscription-billing`, `product-led-growth`, `saas-rate-limiting-and-quotas`, `saas-control-plane-engineering`.
<!-- dual-compat-end -->
## §1 What Entitlements Are
An **entitlement** is "this tenant is allowed to do X" — derived from the tenant's plan, contract overrides, add-ons, and trial state.
Examples:
- "Tenant on Pro plan can have up to 10 users."
- "Tenant on Free plan cannot use the API."
- "Tenant on Enterprise plan has unlimited storage."
- "Tenant on Pro+API_addon can call the API 100k times/month."
- "Tenant in trial has access to all Pro features."
The entitlements engine answers two questions:
1. **Boolean**: "Can this tenant access feature X?" (feature gate)
2. **Limit**: "Has this tenant exceeded its quota of Y this period?" (limit gate)
## §2 The Three Inputs to a Resolution
```
plan baseline → plan_features (tier 'pro' has feature 'reporting')
plan_limits (tier 'pro' has limit 'users' = 10)
contract → tenant_overrides (tenant 123 has feature 'reporting' even on Free)
overrides tenant_overrides (tenant 123 has limit 'users' = 25 by negotiation)
add-ons → tenant_addons (tenant 123 purchased API add-on)
addon_features / addon_limits
```
Resolution precedence: **override > add-on > plan baseline**. Trial state is a special case — usually a tenant in trial inherits the target plan's entitlements.
## §3 Entitlements vs Feature Flags
| | Entitlements | Feature Flags |
|---|---|---|
| Purpose | Commercial gating (what plan allows) | Rollout / experimentation (who sees what) |
| Lifetime | Long-lived; tied to plan | Short-lived; removed after rollout |
| Audience | Tenants (by plan) | Users / tenants / cohorts (by criteria) |
| Source of truth | Billing system + entitlements DB | Feature-flag service (LaunchDarkly, Unleash, PostHog) |
| Default for new code | Inherit plan capabilities | Off (gradual rollout) |
| Audited? | Yes — overrides are commercial decisions | Lightly — flag state changes |
**Keep them separate.** Both runtimes can exist in the same app, but their data models, deploy cadence, and ownership differ. Commercial decisions don't belong in the feature-flag tool, and experimentation doesn't belong in the billing-driven entitlements DB.
## §4 Data Model
```sql
-- Catalogue
CREATE TABLE plans (
code VARCHAR(32) PRIMARY KEY, -- 'free', 'starter', 'pro', 'enterprise'
display_name VARCHAR(64),
trial_days INT,
is_active BOOLEAN NOT NULL DEFAULT TRUE
);
CREATE TABLE features (
code VARCHAR(64) PRIMARY KEY, -- 'api_access', 'sso_saml', 'reporting_export'
display_name VARCHAR(128),
description TEXT
);
CREATE TABLE plan_features (
plan_code VARCHAR(32) NOT NULL,
feature_code VARCHAR(64) NOT NULL,
PRIMARY KEY (plan_code, feature_code),
FOREIGN KEY (plan_code) REFERENCES plans(code),
FOREIGN KEY (feature_code) REFERENCES features(code)
);
CREATE TABLE limits (
code VARCHAR(64) PRIMARY KEY, -- 'users', 'api_calls_monthly', 'storage_gb', 'projects'
display_name VARCHAR(128),
period ENUM('lifetime','monthly','daily','none') NOT NULL DEFAULT 'lifetime',
unit VARCHAR(32) -- 'count', 'bytes', 'tokens'
);
CREATE TABLE plan_limits (
plan_code VARCHAR(32) NOT NULL,
limit_code VARCHAR(64) NOT NULL,
value BIGINT, -- NULL = unlimited
PRIMARY KEY (plan_code, limit_code)
);
-- Per-tenant overrides (enterprise contracts)
CREATE TABLE tenant_feature_overrides (
tenant_id BIGINT UNSIGNED NOT NULL,
feature_code VARCHAR(64) NOT NULL,
enabled BOOLEAN NOT NULL,
reason VARCHAR(128),
expires_at DATETIME,
granted_by BIGINT UNSIGNED,
granted_at DATETIME NOT NULL,
PRIMARY KEY (tenant_id, feature_code)
);
CREATE TABLE tenant_limit_overrides (
tenant_id BIGINT UNSIGNED NOT NULL,
limit_code VARCHAR(64) NOT NULL,
value BIGINT,
reason VARCHAR(128),
expires_at DATETIME,
granted_by BIGINT UNSIGNED,
granted_at DATETIME NOT NULL,
PRIMARY KEY (tenant_id, limit_code)
);
-- Add-ons (e.g., extra seats, API package, storage pack)
CREATE TABLE addons (
code VARCHAR(64) PRIMARY KEY,
display_name VARCHAR(128)
);
CREATE TABLE addon_features (
addon_code VARCHAR(64) NOT NULL,
feature_code VARCHAR(64) NOT NULL,
PRIMARY KEY (addon_code, feature_code)
);
CREATE TABLE addon_limits (
addon_code VARCHAR(64) NOT NULL,
limit_code VARCHAR(64) NOT NULL,
value_delta BIGINT NOT NULL, -- added to base limit
PRIMARY KEY (addon_code, limit_code)
);
CREATE TABLE tenant_addons (
tenant_id BIGINT UNSIGNED NOT NULL,
addon_code VARCHAR(64) NOT NULL,
quantity INT NOT NULL DEFAULT 1,
starts_at DATETIME NOT NULL,
ends_at DATETIME,
PRIMARY KEY (tenant_id, addon_code)
);
-- Usage counters (for limit checks)
CREATE TABLE tenant_usage_counters (
tenant_id BIGINT UNSIGNED NOT NULL,
limit_code VARCHAR(64) NOT NULL,
period_key VARCHAR(16) NOT NULL, -- '2026-05' for monthly, '2026-05-11' for daily, 'lifetime'
used BIGINT NOT NULL DEFAULT 0,
updated_at DATETIME NOT NULL,
PRIMARY KEY (tenant_id, limit_code, period_key)
);
```
## §5 Resolution Strategies
| Strategy | Latency | Freshness | Use case |
|---|---|---|---|
| **JWT-embedded** | < 0.1ms (no I/O) | Until token refresh (15min) | Boolean feature checks; tier-level limits |
| **Runtime DB lookup** | 1-5ms | Real-time | Limit checks needing current counter; just-changed plans |
| **Redis cache + DB fallback** | < 1ms hit / 5ms miss | Configurable TTL | High-traffic feature checks |
| **Hybrid** | Mixed | Mixed | **Default**: boolean checks in JWT, limit checks against Redis counter |
**Default architecture:**
```
Auth issues JWT with: plan, features[], limits[] (snapshot at issue)
On every request:
- Boolean feature check: read JWT (free, instant)
- Limit check: Redis INCR + compare against JWT limit (atomic, fast)
- Periodic re-issue (15min) refreshes JWT against DB
On plan change / override:
- Invalidate user's JWT (force re-issue)
- Update DB
- Emit `entitlements.changed` event
```
## §6 Gate Placement
```
UI gates — Hide / disable features the user can't access. NEVER trust as enforcement.
Show "Upgrade to Pro" CTAs.
API gates — Primary enforcement. Reject with 402 Payment Required or 403 Forbidden + upgrade info.
Worker gates — Background jobs must check too. A bypass of API gates via direct queue insertion is an exploit.
DB constraints — For hard limits (max users per tenant), enforce at DB level too.
```
Pattern for an API gate:
```python
@require_entitlement(feature='api_access')
@require_within_limit(limit='api_calls_monthly')
def api_endpoint(request):
Entitlements.consume_limit(tenant_id, 'api_calls_monthly', amount=1)
# ... work
```
Denial response:
```json
{
"error": {
"code": "ENTITLEMENT_REQUIRED",
"feature": "api_access",
"message": "API access is available on the Pro plan and above.",
"upgrade_url": "https://app.example.com/billing/upgrade?target=pro&context=api"
}
}
```
## §7 Upgrade-Discovery UX
The gate is a sales surface, not just a wall. Every denial:
1. **Tells the user what they tried to do** and why it's blocked.
2. **Names the required plan** explicitly.
3. **Links to one-click upgrade** with deep-link context (so post-upgrade they land back where they were).
4. **Emits a `gate.denied` event** for PQL scoring + lifecycle email.
In-product approaching-limit UX:
- 70% of limit: passive indicator (progress bar).
- 80%: in-app banner suggesting upgrade.
- 95%: stronger CTA + email.
- 100%: hard block with one-click upgrade + email.
## §8 Enterprise Override Model
Enterprise contracts often grant custom entitlements. Implement as **data**, never as **code branches**:
```
Admin Console → POST /admin/tenants/123/entitlements
body: { feature: 'sso_saml', enabled: true, reason: 'Q2 contract Acme', expires_at: '2027-04-01' }
→ writes to tenant_feature_overrides
→ writes audit_log entry
→ emits entitlements.changed event
```
Read-time resolution merges plan + add-ons + overrides automatically.
## §9 Analytics — The Gate Is the PQL Source
Every gate denial is a Product-Qualified-Lead signal. Materialize:
- `gate_denials_per_tenant_per_day` (with `feature`/`limit`, `severity`)
- `tenants_hitting_limit_80pct` (the upgrade pipeline)
- `feature_lock_topN` (which features drive the most upgrade-intent signal)
Feed into `product-led-growth` skill's PQL scoring; coordinate with `saas-lifecycle-email-orchestration` (don't email *and* in-app prompt the same denial — pick one or stagger).
## §10 Anti-Patterns
- **Single big `plans.json` file in the repo** consumed by both UI and API at compile time — drift, redeploys to change limits.
- **No override audit trail** — "who gave Acme unlimited seats?" unanswerable. Fix: every override writes audit_log.
- **Limit check via `SELECT COUNT(*)`** on every request — slow + race-condition prone. Fix: maintained counter + atomic INCR.
- **No expiry on overrides** — a promo grant becomes permanent by accident. Fix: `expires_at` mandatory for promo overrides.
- **No "upgrade context" preserved through the upgrade flow** — user clicks upgrade, lands on pricing page, forgets why. Fix: `upgrade_url` carries `context=` param; post-upgrade redirects back to original action.
## §11 Read Next
- `subscription-billing` — plan / price / subscription primitives.
- `product-led-growth` — PQL + activation; coordinate with gates.
- `saas-rate-limiting-and-quotas` — runtime quota enforcement.
- `saas-control-plane-engineering` — the admin tool that issues overrides.
- `saas-transactional-email-infrastructure` + `saas-lifecycle-email-orchestration` — coordinate gate denials with upgrade email sequences.
## AI Entitlements Addendum
When the SaaS includes AI features, the entitlement catalogue extends with AI-specific keys (model tier, context length, generations/day, tools allow-list, KB size, agent steps, BYOK, fine-tune). The mapping and gateway-enforcement contract live in `ai-entitlements-and-feature-gating`.
Cross-references:
- `ai-entitlements-and-feature-gating` — AI-specific entitlement keys + gateway enforcement.
- `ai-usage-metering-and-billing` — what is gated vs metered.
- `ai-model-gateway` — runtime enforcement chokepoint.
- `ai-on-saas-architecture` — control-plane positioning.Related Skills
saas-tenant-data-portability-and-erasure
Use when designing the GDPR/POPIA/CCPA-compliant data export (right to portability) and erasure (right to be forgotten) workflows for a multi-tenant SaaS — cascade through every data store including warehouse/backups, retention policy, requester verification, audit trail, multi-tenant nuances of erasing one tenant's data without affecting others, and the engineering for African market regulations (Uganda DPPA, Kenya DPA, POPIA).
saas-sso-scim-enterprise-auth
Use when implementing enterprise auth on a multi-tenant SaaS — SAML 2.0 and OIDC SSO with per-tenant IdP configuration, SCIM 2.0 user provisioning/deprovisioning, custom-domain support with automated TLS, IP allowlists per tenant, audit-log API, and the migration from email-password tenants to IdP-enforced tenants. The price of entry for enterprise SaaS.
saas-seeder
Bootstrap a new SaaS from the SaaS Seeder Template: setup database, configure environment, create super admin user, and verify three-tier panel structure. Use when initializing a new multi-tenant SaaS project from this template.
saas-sales-organization
Use when designing or scaling a SaaS sales organisation — sales motions, roles (SDR/BDR/AE/CSM/SE), pipeline stages, lead-to-cash, territory design, quota/commission, sales ops fundamentals, onboarding/ramp, and hiring rubrics. Sourced from "Blueprints for a SaaS Sales Organization" (van der Kooij, Pizarro).
saas-rate-limiting-and-quotas
Use when designing per-tenant rate limits and quotas — algorithm choice (token bucket, sliding window, leaky bucket, fixed window), where to enforce (edge, gateway, service, DB connection pool, queue), per-plan / per-tier limits, soft vs hard caps, fair-queueing for noisy neighbors, headers and error responses, and how to expose quota usage to the tenant.
saas-lifecycle-email-orchestration
Use when designing the six core lifecycle email sequences (welcome/onboarding, behavioral/feature-discovery, upgrade/upsell, retention, reactivation, referral) — trigger contracts, branched automation, suppression rules, PQL/churn-risk triggers, and revenue attribution. Built on top of `saas-transactional-email-infrastructure`. Distinct from `tabler-email-templates` (HTML) and `subscription-billing` (raw billing events).
saas-erp-system-design
Use when designing configurable SaaS or ERP platforms with multi-step business workflows, domain modules, approvals, auditability, pricing and entitlements, operational reporting, and tenant-specific variation. Covers domain boundaries, workflow states, extension points, and control design.
saas-business-metrics
Complete SaaS metrics framework covering revenue (MRR/ARR/ARPU), growth (CAC/LTV/payback), retention (churn/NRR/GRR), engagement, customer satisfaction (NPS/CSAT/CES), unit economics, the Rule of 40, and SaaS finance basics. Use when measuring...
saas-architecture-strategy
Use when architecting or evaluating a cloud SaaS product — including choosing multi-tenant patterns, mapping deployment to IaaS, planning scaling and blast-radius isolation, aligning architecture to business capabilities, and reconciling multi-enterprise consumption requirements with operating-model constraints.
saas-admin-backoffice-tooling
Use when designing the internal admin / back-office console of a multi-tenant SaaS — tenant impersonation (audited, time-boxed), tenant lifecycle controls (suspend/restore/archive/hard-delete), billing operations (refunds, credits, plan overrides), feature-flag overrides per tenant, bulk actions (mass invite, plan migration, region migration), and the audit-log spine that backs all of it. Distinct from the customer-facing super-admin panel in `multi-tenant-saas-architecture`.
saas-accounting-system
Implement a complete double-entry accounting system inside any SaaS app. Users enter transactions naturally (sales, expenses, inventory) while the system auto-posts journal entries under the hood. Produces both user-friendly reports and technical...
multi-tenant-saas-architecture
Use when designing or reviewing a multi-tenant SaaS platform — tenant isolation model, three-panel separation (super admin, franchise admin, end user), zero-trust enforcement, audit trails, and per-tenant permission overrides. Unlike `modular-saas-architecture` which focuses on pluggable business modules, this skill defines the tenancy and auth boundaries that every module inherits.