Flags

Why it's so important not to hard code entitlements when building a SaaS or AI product

fynn
Fynn Glover
·
05/29/2025

Let’s say you’re building a SaaS app with a premium feature — say, exporting reports.

When you hard-code entitlements, the logic might look like this inside your backend:

1if company.plan in ['pro', 'enterprise']:
2    allow_export = True
3else:
4    allow_export = False

Seems simple, right?

But now a customer on the ‘starter’ plan negotiates with sales to get export access. So your developer hacks in a one-off override:

1if company.id == 12345:
2    allow_export = True
3elif company.plan in ['pro', 'enterprise']:
4    allow_export = True
5else:
6    allow_export = False

Then Product adds a new tier.

CS needs to enable exports temporarily for a few accounts.

Marketing wants to run a limited-time trial.

Pretty soon you’re scattering logic like this everywhere:

1if (
2    company.plan in ['pro', 'enterprise', 'growth']
3    or company.id in [12345, 67890]
4    or company.trial_flags.get('export') is True
5    or company.custom_flags.get('export_enabled') is True
6):
7    allow_export = True
8else:
9    allow_export = False

It’s brittle. It’s invisible. Nobody knows who has access to what, or why.

Now multiply that by every feature you gate — usage limits, add-ons, API calls, roles, products — and suddenly your business logic is a landmine.

Pricing experiments? Risky.

Trials? Dangerous.

Billing bugs? Guaranteed.

A robust entitlements layer solves this by externalizing that logic into a structured, queryable system. Instead of coding it in, you check:

1if entitlements.check(company, 'can_export'): # proceed

And that check pulls from a central config: the source of truth for what each company is entitled to — across plans, overrides, trials, whatever.

Clean. Flexible. Safe.