In a multi-tenant product the worst search bug is not a bad ranking — it is one customer seeing another's record. Filtering by tenant in your own backend works until someone forgets a WHERE clause. AACSearch moves the boundary into the key: what a key may read is decided on the server, for every request, regardless of what the client sends.
One collection per customer for hard separation and per-customer schemas, or one shared collection with a tenant field for thousands of small tenants.
Restrict a key to a collection list, or force a filter such as tenant_id on every search it makes. The filter is combined with the caller's own and cannot be removed.
Your backend derives a short-lived key for the signed-in user — narrowed to their collections and your origins — and hands it to the front end.
Collection-per-tenant gives each customer an index of their own: separate schema, synonyms and ranking, and deleting a customer is deleting a collection. It suits fewer, larger tenants. A shared collection with a forced filter suits the long tail — one schema, one set of rules, and a tenant field that the key pins on the server.
Both can coexist in one organization: enterprise customers on dedicated collections, self-serve accounts in a shared one. The application code is the same search call either way.
A scoped key carries its restrictions with it: allowed collections, a forced filter, a field allowlist that hides internal columns, allowed origins and IPs, and a rate limit. They are checked on every request, including each item of a multi_search batch, and the forced filter also applies to suggestions, recommendations and the assistant's retrieval.
Browser keys are derived from a parent key, expire on their own within seven days at most, and die with the parent when it is rotated or revoked — a copied key has a bounded lifetime and a bounded view.
The tenant boundary is applied after the client's parameters, so a crafted request cannot widen it.
A field allowlist keeps cost prices, internal notes and vectors out of responses for keys that should not see them.
One noisy tenant hits its own limit, not everyone's — limits are set per key and per browser key.
Key creation, rotation and revocation are recorded in the audit log and can be sent to your systems as webhooks.
New to the term? The glossary explains Scoped API keys from first principles.
{
"allowed_collections": ["tickets_acme", "contacts_acme"],
"allowed_origins": ["https://app.example.com"],
"expires_in_seconds": 3600,
"rate_limit_per_minute": 300,
"user_token": "u_48121"
}
// -> { "key": "nssk_…", "scope": "search", "expires_at": … }
// search-only, these two collections, this origin, one hourExplore more
The best way to evaluate a search platform isn't reading one more comparison table.
Only then make the decision.