Entitlements
Gate features by subscription plan using feature flags
Feature flags are a natural way to control feature access based on subscription tiers. Instead of hardcoding plan checks throughout your application, use flags with targeting rules to manage entitlements centrally.
Why use flags for entitlements?
| Hardcoded checks | Flag-based entitlements |
|---|---|
| Changes require code deployment | Changes are instant via dashboard |
| Logic scattered across codebase | Centralized in Flagpool |
| Hard to test different plan combinations | Easy to simulate any plan |
| No audit trail | Full audit log of changes |
| Coupled to billing system | Decoupled — works even if billing is down |
Setting up plan-based entitlements
Step 1: Pass the plan in context
Include the user's subscription plan in the SDK context:
const client = new FlagpoolClient({
projectId: 'your-project-id',
apiKey: 'your-api-key',
decryptionKey: 'your-decryption-key',
context: {
userId: user.id,
plan: user.subscription.plan, // 'free', 'pro', 'enterprise'
},
})
<FlagpoolProvider
projectId="your-project-id"
apiKey="your-api-key"
decryptionKey="your-decryption-key"
context={{
userId: user.id,
plan: user.subscription.plan,
}}
>
<App />
</FlagpoolProvider>
Step 2: Create feature flags per capability
Create a boolean flag for each gated feature:
| Flag key | Feature |
|---|---|
advanced-analytics | Analytics dashboard (Pro+) |
audit-logs | Audit logging (Pro+) |
custom-environments | Custom environments (Pro+) |
sso-integration | SSO/SAML login (Enterprise) |
api-access | Public API access (Starter+) |
Step 3: Add targeting rules
For each flag, add rules based on the plan attribute:
Example: advanced-analytics (Pro and Enterprise)
| Priority | Attribute | Operator | Value | Variation |
|---|---|---|---|---|
| 0 | plan | eq | "enterprise" | 0 (enabled) |
| 1 | plan | eq | "pro" | 0 (enabled) |
The default variation is 1 (disabled), so free and starter users don't see the feature.
Step 4: Evaluate in code
if (client.isEnabled('advanced-analytics')) {
showAnalyticsDashboard()
} else {
showUpgradePrompt('Upgrade to Pro for advanced analytics')
}
import { useFlag } from '@flagpool/react'
function AnalyticsPage() {
const hasAnalytics = useFlag('advanced-analytics')
if (!hasAnalytics) {
return <UpgradePrompt feature="Advanced Analytics" plan="Pro" />
}
return <AnalyticsDashboard />
}
Numeric entitlements
Use number flags for limits that vary by plan:
Flag: max-upload-size-mb
| Variation | Name | Value |
|---|---|---|
| 0 | Free | 10 |
| 1 | Pro | 100 |
| 2 | Enterprise | 1000 |
Rules:
| Priority | Attribute | Operator | Value | Variation |
|---|---|---|---|---|
| 0 | plan | eq | "enterprise" | 2 |
| 1 | plan | eq | "pro" | 1 |
Default variation: 0 (Free tier limit)
const maxUploadMb = client.getValue('max-upload-size-mb') // 10, 100, or 1000
if (file.size > maxUploadMb * 1024 * 1024) {
showUpgradePrompt(`Upgrade for uploads up to ${nextTierLimit}MB`)
}
Handling plan changes
When a user upgrades or downgrades, update the context:
// User upgrades from free to pro
client.updateContext({ plan: 'pro' })
// All flags immediately re-evaluate with the new plan
// User now has access to pro features
In React, update the context prop or use setContext:
const { setContext } = useFlagpool()
// After successful upgrade
setContext({ plan: 'pro' })
Trial periods
Combine plan-based rules with a time-based attribute for trial access:
const context = {
userId: user.id,
plan: user.plan,
isTrial: user.trial?.isActive,
}
Then add a targeting rule: isTrial eq true → enabled (with higher priority than the plan-based rules). When the trial expires, update the context and the user falls back to their actual plan's entitlements.
Next steps
- Targeting — all operators and rule configuration
- Flag Types — number flags for limits
- Contexts — passing plan and user attributes