How to · Building

One API Key, Thousands of Users: the Architecture That Follows

By Ghiles Asmani, founder of Weckr · Published August 15, 2026

Short version: the standard architecture is one server side provider key behind your backend, serving every user. The moment you adopt it, four things silently transfer from the provider to you: knowing who used what, knowing who cost what, limiting who can use how much, and stopping whoever runs away. The provider sees one customer, you. Your users exist only in your request path, so every per user question has to be answered there, at call time.

This is the second article in the shipping sequence, after the API key proxy pattern establishes the chokepoint.

Why one key (and why not per user keys)

Per user provider keys look like clean isolation and collapse in practice: provisioning and rotation across thousands of keys, provider dashboards not built for it, rate limits fragmenting per key, and secrets multiplying. Providers themselves expect the aggregator pattern: you are their customer, your users are yours. Split keys by environment and maybe by service (prod, staging, worker), not by user. The one partial exception, letting users bring their own key, is a product decision with real tradeoffs, covered in BYOK vs managed keys.

The four problems you now own

  • Attribution. Which user, which feature, which tokens. Tag at call time or it never exists, the mechanics of tracking AI costs per user.
  • Cost. Tokens times current rates, per user, compared to what they pay. This is where the quiet unprofitable account becomes visible, or does not.
  • Limits. Per user request rates and spending caps at your chokepoint, since the provider can only limit you in aggregate. Detail in rate limiting your AI endpoints per user.
  • Runaways. One looping integration burns the shared token pool and the shared budget; velocity detection per user catches it mid burst, per AI agent loop detection.

The shared pool point deserves emphasis: when your users collectively hit provider rate limits, every user sees errors while one or two caused them. Without per user data, your only lever is buying a higher tier; with it, the fix is one cap on one account.

The pattern, concretely

// every AI call in your backend carries the user context
const result = await wk.chat(openai, {
  model: 'gpt-5.4-mini',
  messages,
  userId: user.id,          // attribution
  feature: 'ai-search',     // per feature cost
  plan: user.plan,          // margin + cap enforcement
});

With Weckr, that one call shape does all four jobs: the log records tokens and recomputes cost server side at current rates, the dashboard shows cost and margin per user and feature, caps block or downgrade a user who exceeds their plan’s monthly budget before the call is made, and velocity alerts fire on runaway patterns. Building the same by hand is a reasonable few weeks, the pieces are described across this site, but it is undifferentiated plumbing, and the price table maintenance alone is a recurring tax, per LLM price history.

FAQ

Should each user of my app get their own OpenAI API key?

No. One server side key (or a few, split by environment or service) serving all users through your backend is the standard architecture. Per user provider keys mean provisioning, rotation, and rate limits fragmenting across thousands of keys, and providers do not design for it. The consequence you must then own: usage, cost, limits, and abuse become per user problems in your code, because the provider sees only your key.

How do I know which user caused which OpenAI costs?

Attribute at request time. Every call goes through your backend anyway, so tag it with your user id and feature, read the usage object token counts from the response, and price them at current rates. Store that, and cost per user per month is a query. Nothing at the provider can reconstruct this after the fact, the attribution exists only if your code records it when the call happens.

How do I stop one user from consuming everything?

Layered limits at your chokepoint: a request rate limit per user for basic abuse, an input size and max_tokens bound for worst case request cost, and a monthly spending cap per user that blocks or downgrades to a cheaper model when exceeded. Cost based limits matter most because request counting misses the asymmetry: one user’s requests can cost 100 times another’s.

What happens at the provider when my users collectively hit rate limits?

Your app shares one pool of requests and tokens per minute, so a spike from a few heavy users starves everyone: other users see errors while the provider correctly reports you, singular, as the one hitting limits. This is why per user visibility matters even before billing: when 429s start, the first question is which user is eating the minute, and aggregate dashboards cannot answer it.

What is the minimal stack for multi user AI cost management?

A backend proxy with auth, a user id and feature tag on every call, per request usage logging with server side cost computation, per user monthly caps, and a velocity alert for runaway loops. That is a few weeks to build well, or two lines with Weckr: wrap your existing client, pass userId, feature, and plan, and the tracking, margins, caps, and loop detection are done.

Keep reading

The architecture is one key. The visibility is two lines.

Every multi user AI app converges on this shape; the difference is whether the per user layer exists before or after the first incident. Weckr is that layer prebuilt: attribution, cost, margin, caps, and loop detection from one wrapper, free for 50,000 requests a month. See a multi user dashboard live on the demo, or start with the AI cost and margin guide.

See the dashboard with real data, no signup needed.

Try the demo →