Read the customer's effective plan entitlement at runtime, then authorize the metered operation before expensive work begins. For a media service that invoices per customer, the decisive constraint is plain: a strict spend ceiling means some valid requests must be refused; a permissive path can accept usage the account did not authorize.
Short answer: hardcoded limits belong to invariant engineering guardrails, while customer plan limits belong in evaluated policy data. The smallest useful experiment is to prove that one account cannot spend the same remaining unit twice under concurrent requests, and that a plan change leaves an auditable version on every accepted usage event.
I would not turn a plan label into billing logic. A label is descriptive; an effective entitlement needs a period, a unit definition, a ceiling, an effective time, and a version. This distinction matters even more for AI-assisted media workflows, where a request can trigger costly generation after a queue hop.
What did the runtime experiment show?
The simple approach was a dictionary in application code: starter: 250, team: 2500, followed by an if used < limit check. It is a reasonable notebook shortcut.
Once support changes an allowance, finance changes a ceiling, or an account moves between plans, it creates a second copy of commercial policy in the repository. A deploy becomes part of a billing change. The chosen approach keeps the effective entitlement in a current-period record and evaluates it with the usage update. PostgreSQL documents row-level locking and transaction isolation because concurrency rules only mean something at a transaction boundary. For a strict ceiling, absence of a current entitlement is a refusal, not an invitation to guess. That rule means an operator must make the policy record available before billable traffic can proceed, and it makes the refusal observable instead of silently turning a missing read into unpriced work.
Here is the focused test case: account media-42 has 12 remaining article units in period 2026-09. Two requests each ask for 8 units. Exactly one should be authorized. The other should receive quota_exhausted, and the accepted event should retain the entitlement version that made that decision.
This is the key trade-off.
Refusals are visible and supportable; unbounded overage is harder to explain on an invoice.
Reading plan entitlements at runtime vs hardcoding limits: where is the boundary?
Use a hardcoded value for a universal technical guardrail, such as a maximum payload size chosen to protect every caller. Do not present that guardrail as a customer contract. It does not need an account, billing period, or mid-period change rule.
Read a plan entitlement at runtime when its value can vary by account or time, when accepted work must reconcile with an invoice, or when a policy change must take effect without a deployment. The runtime read introduces a dependency and demands an explicit failure policy. With a strict ceiling, reject billable work when the policy cannot be evaluated, or rely only on a previously validated record within a deliberately defined validity window. Both choices have operational consequences.
| Question | Hardcoded limit | Runtime entitlement |
|---|---|---|
| Who changes it? | Engineering through a deployment | The owner of account policy |
| Can it differ by customer? | Only by adding branching code | Yes, through the evaluated record |
| What explains an accepted unit later? | A code revision and surrounding logs | An entitlement version plus the usage event |
| Primary failure mode | Stale commercial policy | Refused traffic or overage, depending on the failure rule |
The table is not an argument for reading every configuration value on every request. It is a way to keep two different classes of policy from being casually mixed.
A cache can still be appropriate, but it needs a period-aware key and a stated expiration or invalidation rule. A cache keyed only by account ID can carry an old allowance over a billing rollover.
A minimal FastAPI authorization path
The application owns enforcement; the account-policy system owns the commercial terms. In the example below, the database transaction serializes each account-period decision by locking its entitlement record, then conditionally increments the usage ledger. The response is intentionally a normal decision object. Quota exhaustion is an expected business result.
from dataclasses import dataclass
from datetime import datetime
@dataclass(frozen=True)
class MeterDecision:
allowed: bool
reason: str
entitlement_version: int | None = None
def authorize_article_generation(
conn, account_id: str, period_key: str, requested_units: int, now: datetime
) -> MeterDecision:
if requested_units <= 0:
return MeterDecision(False, "invalid_usage")
with conn.transaction():
entitlement = conn.execute(
"""
SELECT quota_units, entitlement_version
FROM account_entitlements
WHERE account_id = %(account_id)s
AND period_key = %(period_key)s
AND effective_at <= %(now)s
FOR UPDATE
""",
{"account_id": account_id, "period_key": period_key, "now": now},
).fetchone()
if entitlement is None:
return MeterDecision(False, "no_current_entitlement")
usage = conn.execute(
"""
INSERT INTO account_usage AS usage (account_id, period_key, used_units)
SELECT %(account_id)s, %(period_key)s, %(requested_units)s
WHERE %(requested_units)s <= %(quota_units)s
ON CONFLICT (account_id, period_key) DO UPDATE
SET used_units = usage.used_units + EXCLUDED.used_units
WHERE usage.used_units + EXCLUDED.used_units <= %(quota_units)s
RETURNING used_units
""",
{
"account_id": account_id,
"period_key": period_key,
"requested_units": requested_units,
"quota_units": entitlement["quota_units"],
},
).fetchone()
if usage is None:
return MeterDecision(
False, "quota_exhausted", entitlement["entitlement_version"]
)
return MeterDecision(True, "authorized", entitlement["entitlement_version"])
The schema behind this snippet needs a uniqueness constraint on account_usage(account_id, period_key) for the conflict target to be valid. It also needs a clear rule for multiple effective entitlements in the same period; selecting one arbitrarily would make the policy ambiguous. Those are data-model decisions, not framework features.
For asynchronous generation, reserve units before enqueueing work and define how an expired reservation returns to the balance. Charging only after a worker finishes can overshoot a strict ceiling when many jobs are already in flight. The unit should also be explicit: generated articles, model tokens, or a weighted invoice unit are different measures and should not be combined in one ledger column.
What should be measured before copying this design?
Measure policy-read latency separately from generation latency, refusal rate by entitlement version, reservation expiry, retries that reuse a usage-event identifier, and the difference between the usage ledger and invoice totals. The point is not a generic performance score. It is finding out whether the selected ceiling produces an acceptable refusal rate while preserving the invoice boundary.
An eval harness should cover no active entitlement, exact exhaustion, concurrent increments, a period rollover, a downgrade, and a retry that reaches the meter twice.
The happy path is easy. The boundary cases decide whether the ledger can be trusted.
Credentials for the entitlement source deserve their own boundary too. The OWASP guidance calls for least privilege, rotation, and auditability in secret management. Keep service credentials out of entitlement records and source code, so a worker can receive only the access it needs to consume or release a reservation.
The decision rule for a metered media invoice
For a media account billed on metered usage, evaluate the current entitlement before the costly step, atomically record accepted usage, and attach the evaluated version to the event. Hardcode only technical guardrails that never represent customer terms.
Choose the failure rule deliberately: refuse traffic to protect a firm spend ceiling, or accept controlled overage if serving the request outweighs the ceiling. The code is short. Defining the unit, effective-time behavior, and refusal policy is the real work.
Top comments (0)