StrataDocs

Rate limits and quotas

The throttles that keep one heavy user from starving the rest of the org and cap your overall spend.

Strata enforces two kinds of limit. Per-user limits are a rolling 1-hour ceiling resolved per person through a cascade (user override → role → org → env fallback). An org pool is a single shared monthly token bucket the whole organization draws from, with an optional per-user soft cap. You pick one plan for the org; both are configured under Organization settings, along with the separate agent quotas (agents-per-user, agent-runs-per-day, minimum interval, and per-run/per-month cost ceilings). All of this requires canManageOrgSettings to change.

One enforcement engine sits behind every paid surface — web chat, the Teams bot, scheduled and webhook agent runs, voice mode, and the REST API — so no surface can bypass the cap.

Two plans: per-user limits vs. org pool

Under Organization settings → Defaults → Quotas & rate limits → Rate-limit plan, choose how the org is throttled:

  • Per-user limits (default) — every person gets their own rolling 1-hour ceiling. The number and unit come from the cascade below. Best when you want predictable per-person fairness.
  • Org pool (shared bucket) — the whole org shares one monthly token pool. Anyone can draw from it until it runs dry, with an optional per-user soft cap so no single person drains it. Best when you'd rather manage one number for the whole org than tune per-person limits.

The rest of this page covers per-user limits first, then the org pool.

Per-user limits: two units (chats vs. tokens)

Every rate limit is per hour in a sliding window, and uses one of two units:

  • chats — count of chat messages sent in the last 60 minutes. Tracked in an in-memory sliding window per user, evicted after an hour of inactivity. Fast and easy to reason about — "100 chats per hour" means at most 100 chats per hour.
  • tokens — sum of total_tokens from activity_log over the last 60 minutes. Tracked against the database, captures real cost more precisely. A heavy single chat (1M tokens of context) counts as more than a quick "hi."

A chats-mode default of 60 chats/hour is what every org gets out of the box (the CHAT_RATE_LIMIT_PER_HOUR env fallback). Switch to tokens mode when you want to bill heavy power users without artificially capping conversation volume.

The cascade

In the per-user plan, the effective rate limit for any one user is resolved by getEffectiveRateLimit(userId):

limit cascades user → role → org → env
unit  cascades role → org → 'chats'

In plain English:

  1. If the user has user_settings.rate_limit_override set to a positive number, that is the limit. The unit still comes from the user's role (or the org if the role does not specify, or chats if neither does).
  2. Else if their role has default_rate_limit set, that is the limit and the role's default_rate_limit_unit is the unit.
  3. Else if the org has default_rate_limit set, that is the limit and the org's default_rate_limit_unit is the unit.
  4. Else the env fallback (CHAT_RATE_LIMIT_PER_HOUR, default 60) in chats mode.

The unit cascade is deliberately role → org → chats (not user → role → org) — a per-user override changes the number, not the unit, because flipping one user from chats to tokens while the rest of the role uses chats produces confusing billing semantics. Pick the unit once at the org or role level.

Setting an organization default

Organization settingsDefaults → Quotas & rate limits. With the Rate-limit plan set to Per-user limits, the Default rate limit (per 1 hour) control appears.

Two controls:

  • Number input — leave blank to inherit the env fallback (60 chats/hour). Any positive number sets the org default.
  • Unit toggle to the right of the number — flips between chats and tokens. Switching units recalculates the displayed number using AVG_TOKENS_PER_CHAT = 5000 so a 60 chats value becomes 300,000 tokens and vice versa. Empty stays empty.

Organization settings auto-save — there is no Save button. Each change writes silently to the server (a short debounce coalesces rapid edits). The change takes effect on the next chat request from any user whose role does not override it — and applies the same way across Teams, agents, and voice.

Setting a role default

Roles → click a custom role → Defaults for new users in this roleRate limit (per hour).

Same number + unit toggle. The role's unit is what users in that role get unless they have their own override.

Setting a per-user override

Users → click Manage → Profile & Access tab → rate limit input.

The number is the user's rate_limit_override. Leave blank to clear and fall back to the role/org default. The unit shown is the user's effective unit — driven by their role and org, not by this input.

The audit log records the change as user.rate_limit_changed with the new value.

Note

A per-user override only applies under the per-user plan. When the org runs on the org pool, the per-user soft cap governs each person instead.

Switching to an org pool

Organization settingsDefaults → Quotas & rate limitsRate-limit planOrg pool (shared bucket). Three controls appear:

  • Monthly token pool — total tokens the entire org can consume each month. Leave blank to disable the pool and fall back to per-user limits.
  • Per-user soft cap — the maximum share of the pool any single user can consume in a reset cycle, as a percentage (1–100). For example, 30 means no one user can use more than 30% of the monthly pool. Blank disables the per-user cap so anyone can draw the whole pool.
  • Pool reset day — the day of the month (1–28) the pool resets to zero at 00:00 UTC.

These controls auto-save as you edit them — there is no Save button.

In pool mode the cascade and the chats/tokens unit no longer apply — usage is always measured in tokens against the shared bucket. Two ceilings are enforced:

  1. Org-wide — once total usage since the last reset reaches the monthly pool, every user is blocked until the next reset day.
  2. Per-user soft cap (if set) — once a user reaches their share of the pool, they're blocked but others keep their headroom.
Warning

The org pool resets monthly, not hourly. A user who hits the org-wide ceiling can't send again until the pool reset day, which may be weeks away — size the pool generously.

What the user sees at the limit

When a chat request would exceed the policy, the server returns HTTP 429 with:

  • A Retry-After header — seconds until the oldest item in the window ages out (chats mode), or 3600 for tokens mode.
  • A JSON body:
{
  "error": "Rate limit exceeded. You've sent 60 messages in the last hour. Try again in 12 minute(s).",
  "retryAfter": 720,
  "unit": "chats",
  "used": 60,
  "limit": 60
}

For tokens mode:

{
  "error": "Rate limit exceeded. You've used 305,210 of 300,000 tokens allowed per hour. Try again shortly.",
  "retryAfter": 3600,
  "unit": "tokens",
  "used": 305210,
  "limit": 300000
}

For the org pool, the unit field tells the user which ceiling they hit — org_pool for the org-wide bucket or pool_user_cap for their personal soft cap:

{
  "error": "You've reached your 30% share of your organization's monthly token pool (15,000,000 of 15,000,000). Others still have headroom — contact your admin if you need more.",
  "retryAfter": 3600,
  "unit": "pool_user_cap",
  "used": 15000000,
  "limit": 15000000
}

The Chat UI renders this as an inline rate-limit card explaining what was hit and when the limit resets. The Settings page also exposes a /api/chat/usage endpoint that drives a live usage bar so users can see their consumption against the same policy without having to hit the cap. Under the org pool, that card switches to reflect the user's share of the shared monthly pool.

Per-user analytics

Every time a user is blocked, Strata writes a row to rate_limit_hits (debounced to one row per user per 5 minutes — retry spam does not bloat the table). The Usage page surfaces these:

  • "People are at their hourly limit" (or "Person is at their hourly limit" for exactly one) — appears in the Usage summary only while someone is actually limited, and is absent otherwise rather than showing zero. Counts users whose at_limit flag is set in the current poll.
  • Users in red in the All users table — anyone currently at their hourly limit.
  • Per-user counts in the billing profile drill-down.

These are useful for spotting:

  • One user systematically hitting the cap (probably needs an override).
  • A role default that is too tight for the team's real workload.
  • A pattern of bursts that should trigger a unit switch from chats to tokens.

Agent quotas (separate from rate limits)

Six org-wide quotas govern scheduled agents, configured under Organization settingsDefaults → Quotas & rate limits:

  • Max agents per user — cap on how many scheduled agents one user can deploy. Blank = unlimited.
  • Max agent runs per day (per user) — daily ceiling on aggregate scheduled agent runs across all of one user's agents. Blocks runs once hit; resets at UTC midnight. Blank = unlimited.
  • Minimum interval between runs (seconds) — reject schedules more frequent than this. e.g. 300 = "no more than every 5 minutes." Blank = no floor.
  • Max tokens per agent run — hard ceiling on total tokens a single run may consume. The run stops mid-execution once it's reached — the key guard when you allow short (every-few-minutes) schedules. Recommended 60,000–150,000. Blank = no limit.
  • Max spend per agent run — dollar ceiling for one run, in cents (100 = $1.00). The run aborts once its estimated spend crosses this. Recommended 50–200¢. Blank = no cap.
  • Monthly spend cap per agent — total each agent may spend per calendar month, in cents. Once reached, that agent's runs are skipped until the month resets. Blank = no cap.

The org-wide kill-switch lives on a separate lock: Organization settingsLocksAgents. When ON, no one in the org can create or edit agents — already-deployed agents stay paused-but-visible. Per-role canCreateAgents permission still applies on top.

Organization spend ceiling

The agent quotas above cap spend one run or one agent at a time. The org also carries a single monthly AI spend ceiling — an absolute dollar cap on the whole organization's AI usage. Unlike the per-agent quotas, this ceiling lives under Billing and is gated on canManageBilling, not canManageOrgSettings.

When month-to-date spend crosses the ceiling, Strata pauses AI on every surface — web chat, the Teams bot, scheduled and webhook agents, voice, and the REST API — cutting a response mid-stream if a single turn is what tips it over. An admin inbox notice fires once for the period, and the ceiling auto-resumes at the start of the next month. Leave it blank for no cap. The full setup lives in Billing.

What can go wrong

ErrorWhat it means
User reports they cannot send messagesCheck their effective policy with the Users Manage modal. If the displayed limit is much lower than expected, the cascade is resolving to a different level than you think.
Rate limit exceeded on the first message of the dayThe window is a rolling 60 minutes, not a calendar day — yesterday's late-night burst can still count. (Per-user plan only.)
Bumping a user's override has no effectSave was successful but the user has cached the rate-limit policy. They will see the new value on their next chat. Or the org runs on the org pool, where per-user overrides don't apply.
Everyone in the org is suddenly blockedThe org pool has hit its monthly ceiling. Nobody can send until the pool reset day. Raise the pool or wait for the reset.
KPI "Users at hourly limit right now" never appearsNobody in your org is currently blocked. This is normal.
Agent fails to deploy with "schedule too frequent"Reduce the schedule to at or above your Minimum interval between runs.
User cannot create an agent despite canCreateAgents = trueThe org's Agents lock is on, or the user's per-user agent governance has the lock-creation toggle set. Check both.

See Roles and permissions for the default_rate_limit field on roles, Usage for the analytics, and Per-user agent governance for the per-user agent controls.

Related