Track spend where it is incurred and enforce ceilings before the call, not in a monthly invoice review.
sql create table ai_usage ( id bigserial primary key, user_id uuid not null, feature text not null, model text not null, prompt_tokens int not null, completion_tokens int not null, cost_usd numeric(10,6) not null, created_at timestamptz not null default now() ); create index ai_usage_user_day on ai_usage (user_id, created_at desc);
ts
const spent = await dailySpend(userId);
if (spent > planCap(user.plan)) throw new QuotaError("daily AI limit reached");Gateway error semantics matter here: 429 is transient — back off honouring `Retry-After`; 402 and 403 are terminal — surface the message and stop, and for background jobs persist a paused state so every scheduled run checks it before doing work. Never auto-retry a 402 or 403.
Cheapest real savings, in order: prompt caching on a stable prefix, model routing by task difficulty, shorter retrieved context, and deduplicating identical requests.
Exercise: write usage rows for every call, build a per-feature daily cost view, and add a hard cap that returns a clear message instead of a stack trace.