Quotas
How AACsearch enforces plan limits — soft caps, hard caps, overage, the quota reset schedule, and what happens when you go over.
A quota is a plan limit measured over a period. AACsearch ships four quotas (search units, indexed documents, connector syncs, AI wallet) and three thresholds per quota (soft cap at 80%, hard cap at 100%, overage above 100%). This page describes how the gates fire and what you see when they do.
The quota gate
Every search and ingest request goes through a stack of gates in this order:
Auth gate (valid key + org)
→ Feature gate (plan allows this operation)
→ Quota gate (org has remaining units in the period)
→ Rate gate (per-key rate limit not exceeded)
→ Search engineThe quota gate calls checkQuota(orgId, "search") in packages/api/modules/entitlements/middleware/quota-check.ts. It returns one of:
allowed: true— proceed.allowed: false, reason: "search_quota_exceeded"— 429 response.allowed: true, isSoftCap: true— proceed but the response carries an advisory header.
Soft caps (80%)
At 80% of any quota the dashboard surfaces a warning and the API attaches an advisory header to every response:
X-Aacsearch-Quota-Warning: search 82% used; resets 2025-11-01T00:00:00ZThe header is purely informational — requests still succeed. Use it to drive your own alerting (Datadog monitor, Slack webhook, etc.) instead of relying on dashboard email alerts.
Dashboard surfaces:
- Orange banner on
/[orgSlug]/overviewand/[orgSlug]/settings/billing. - Quota tile shows
82% usedin warning color. - A one-time email to billing contacts when each quota first crosses 80% in a period.
Hard caps (100%)
At 100% the gate flips and requests are rejected:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{
"error": "search_quota_exceeded",
"detail": "Monthly search quota reached. Upgrade or wait for the period reset.",
"quota": "search",
"limit": 1000000,
"used": 1000000,
"resetsAt": "2025-11-01T00:00:00Z"
}What stops at the hard cap depends on the quota:
| Quota | At hard cap, what stops? | What still works |
|---|---|---|
| Search units | New POST /search, multi-search, suggest | Dashboard reads, admin operations |
| Indexed documents | New ingest (PUT documents, batch, connector full/delta sync) | All reads |
| Connector syncs | New sync runs (heartbeats still work; pending syncs queued) | Reads, ingest via REST |
| AI wallet (balance 0) | Knowledge, embeddings, rerank, summarize, chat | Search, ingest, everything non-AI |
Failures emit SearchUsageEvent with type: "quota_block" so they show up in Analytics → Failed.
Overage (above 100%, paid plans only)
Paid plans can opt in to overage — a metered, post-paid amount billed at end of period for usage beyond the hard cap. When overage is enabled (/settings/billing → Allow overage):
- Requests above the hard cap continue to succeed instead of returning 429.
- Each overage unit is recorded in
OverageTransactionwith a per-unit price (currently $0.0001 per search unit for Pro, lower for Business — exact rates inpackages/payments/lib/entitlements.ts). - The dashboard shows
Overage so far this period: $4.32on/settings/billing. - The next invoice includes one line per quota with overage.
Overage is off by default on Pro and on by default on Business. Free and Starter cannot enable overage — they always hard-cap.
To prevent runaway bills, set a spending limit on the org (/settings/billing → Spending cap). When the limit is hit, overage stops and 429s resume.
Quota reset schedule
Quotas reset on the first day of your billing period. Most customers are on monthly billing; the reset is at 00:00:00 UTC on the 1st of the month. Annual customers reset on the anniversary of their first payment.
You can see the next reset on /[orgSlug]/settings/billing and in the X-Aacsearch-Quota-Reset header on any response near the cap.
Reset behavior:
- The counter goes back to 0.
- Overage charges from the previous period are billed on the renewal invoice — they do not affect the new period's limits.
- Spending caps reset to the configured value.
There is no rollover. Unused quota does not carry forward to the next period.
Soft vs hard caps — when each makes sense
Default behavior:
- Searches — hard cap at 100%. Going past quota means runaway widget traffic; the protection is worth the user-visible 429.
- Indexed documents — hard cap at 100%. Writing more than your steady-state cap usually means a bug in the connector; blocking ingest is the right default.
- Connector syncs — soft cap at 100% for the first month after the cap is breached, then hard cap. Gives operators a window to either raise the plan or stretch the sync interval.
- Wallet — always hard cap (zero balance = no AI). There is no soft mode for the wallet because micro-USD draws can be arbitrarily fast.
The defaults live in packages/payments/lib/entitlements.ts. Enterprise customers can override per-quota via their contract.
Grace periods after cancellation
When you cancel a paid plan, you keep full access until the end of the paid period. After that:
- Reads — granted for 7 more days at the previous plan's limits. This window is the grace period for reads.
- Writes — stop immediately at the end of the paid period. No grace.
The grace period exists to let you re-subscribe without data loss. After 30 days of no payment, dormant indexes are flagged for archival and the wallet balance is preserved indefinitely.
For details: Upgrade & downgrade.
Diagnostics
When a quota fires, check:
/[orgSlug]/overview— quota tile and percent used./[orgSlug]/analytics— per-day chart shows when the spike happened./[orgSlug]/analytics→ Failed tab —search_quota_exceededfailures.X-Aacsearch-Quota-*response headers — programmatic check./admin/wallet(admin only) — wallet-specific draw history.
If a 429 surprises you, the audit log will not help — quota blocks are not audit events (they happen on every blocked request and would flood the log). Use the analytics view instead.
API response headers
Every successful request includes:
| Header | Meaning |
|---|---|
X-Aacsearch-Quota-Used | Units consumed in the current period |
X-Aacsearch-Quota-Limit | Hard-cap value for this org |
X-Aacsearch-Quota-Reset | ISO-8601 timestamp of the next reset |
X-Aacsearch-Quota-Warning | Set only above 80%; format: <quota> N% used; resets … |
Use these in production code instead of polling the dashboard.
Related
- Plans — plan matrix with quota caps.
- Usage units — what counts as a unit.
- Wallet & AI credits — wallet quota mechanics.
- Errors and rate limits — full HTTP error catalog including 429 shape.
- Plans & Limits (architecture) — entitlements code paths.