Skip to content
Run the businessCommercial platform

Usage limits

One runaway user can't run up your bill.

Set limits per plan: how many projects, how much AI, how many requests. The server enforces every limit at the moment of the write, so nobody sneaks past a grayed-out button. And retries never burn quota twice.

3
kinds of limits: per window, per billing period, at once
1
durable usage record behind every decision
0
limit decisions made in the browser

Product example

See it working

This is the same visual component used by the authenticated app, rendered with deterministic sample data.

Scenario
viewport
surface theme
mode

Within limits

Review included allowance, enforced limits, and remaining capacity.

Inert sample data · no network access

Current usage

How much of the current plan this workspace has consumed in the open billing windows.

Credit balance

Prepaid credits available to this organization

0

Base subscription + usage

Included units
1,000
Overage units
0
Estimated usage charge
$0.00

Current-period overage only, before taxes and subscription fees. Your provider invoice is final.

Active projects

6 / 25

x
Server enforcedWindow ends Sep 1, 2026

19 remaining

25 Included in your plan

AI generations

684 / 2,500

x
Server enforcedWindow ends Sep 1, 2026

1,816 remaining

1,000 included before overage

Authenticated API requests (all organizations)

42 / 120

x
Enforced on integrated API routesWindow ends 9:31 AM

78 remaining

Preview ready

The problem this solves

Without a shared foundation, every team rebuilds these edge cases — differently.

The disabled button that wasn't

You gray out the button when a user hits their limit. Then someone calls the API directly, or keeps an old tab open, and blows right past it. A disabled button is not enforcement. The server deciding at write time is.

Paying customers locked out

A flaky network retries a request. A naive counter charges the quota twice. Now a paying customer is locked out of an allowance they never actually used, and they're right to be mad.

Nobody knows what Pro includes

Limits scattered across ad hoc if-statements drift apart until support asks what a plan actually allows and nobody can answer with confidence. One registry ends that.

Highlights

Why it matters

One list of limits

Every limit lives in one typed file, so what each plan allows is written down in exactly one place.

Retries don't count twice

Each use carries a stable ID. A retried request gets the original answer back instead of charging quota again.

Locked by default

If the server can't tell what plan someone is on, the answer is no. Nothing slips through by accident.

How it works

The mechanism end to end, as implemented in the repository.

  1. 1

    Declare the limit once

    Each limit is one typed entry: what it counts, who it applies to, the time window, and what happens when it's hit.

  2. 2

    The server finds the plan

    It maps the subscription to a plan and its limits. A late payment gets a short grace window before access tightens.

  3. 3

    Usage is reserved inside the write

    The server locks, reads the usage ledger, and reserves the quota in the same transaction as your write. Races and retries settle safely.

  4. 4

    Clear errors, not mystery 500s

    A rate limit tells the caller exactly when to retry. A plan limit says so plainly, which is your upgrade prompt. The UI meters just explain the decision.

Engineering guarantees

What this does and does not promise

Safety boundary

The meters in the UI only explain decisions, they never make them. The server re-checks every limit inside the write itself, and an unknown plan means denied, not allowed.

Implementation evidence

The boundary above is code, not a claim. These files carry the contract:

  • src/registries/quotas.ts
  • src/server/commercial-access.ts
  • config/entitlements.ts
Questions

Frequently asked questions

Build on the usage limits foundation

The docs describe the same contracts this page demonstrates.