Every customer’s data in its own namespace, not behind a filter.
For SaaS copilots and assistants: your backend writes each customer’s documents to their namespace, and the copilot searches with a key that reaches theirs alone. Exact, regex, filtered and vector retrieval; idle customers cost only their bytes.
From recorded runs, with how each was measured, on the benchmarks page.
A namespace per customer
Made by its first write, with no limit on how many on pro. A customer’s data is one prefix in object storage: easy to reason about, count, export or delete.
The key is the boundary
Your copilot calls SkimmerDB with a key that reaches one workspace. A bug, a missing filter or a prompt injection can’t widen that: the rest answer 404.
Recall that matches how people ask
Vectors for meaning, literal and regex search for names and numbers, metadata filters for source, owner and dates, all in one query. Exact counts when a user asks “how many”.
A shared index with a filter, or a namespace each
| One shared index | SkimmerDB | |
|---|---|---|
| Where a customer’s data lives | One shared index, every row tagged with tenant_id | Its own namespace |
| What keeps customers apart | A filter your code must never forget | The key: other namespaces don’t exist for it |
| A customer leaves | Delete by filter, hope nothing was missed | Delete the namespace |
| A big customer arrives | The shared index grows; everyone’s queries scan more | Its namespace grows; the others don’t change |
| Idle customers | Kept in the same hot index as active ones | Bytes in S3, no compute |
| Exact matches (ids, codes, names) | Often a second system next to the vector index | The same query, the same copy |
Sync from your backend, retrieve from the copilot
Documents are an id, text, metadata and an embedding if you have one. Writing an id again replaces it, so syncing a changed document is one write.
# your backend: one namespace per customer workspace W=https://api.skimmerdb.com/v1/namespaces/ws-4812 curl $W/docs -H "Authorization: Bearer $ADMIN" -d '{ "docs": [{"id": "doc-91#3", "text": "Q3 renewal terms for Globex: 12% uplift, net 45", "meta": {"source": "drive", "owner": "maria", "updated": 20261012}, "vector": [0.12, -0.03, ...]}]}' # a customer leaves: everything they stored goes with one call curl -X DELETE $W -H "Authorization: Bearer $ADMIN"
# the copilot, for a user of workspace 4812 curl $W/search -H "Authorization: Bearer $WS_KEY" -d '{ "vector": [0.04, 0.17, ...], "q": "globex", "filter": {"source": ["drive", "crm"]}, "limit": 8}' # "how many open deals mention net 60?" counted, not guessed curl $W/count -H "Authorization: Bearer $WS_KEY" -d '{ "q": "net 60", "filter": {"source": "crm", "stage": {"ne": "closed"}}}'
One key per customer
Make a key when a workspace is created and hand it to the copilot that serves it. Change its reach or caps at once; revoke it at once.
- Scoped. Read, write or admin, limited to names or a prefix like
ws-4812-*. - Capped. Requests a second, queries and writes a billing period.
- Accounted. Every answer reports its latency, object-store reads and CPU.
# a key per workspace, made when the workspace is
curl https://api.skimmerdb.com/v1/keys -H "Authorization: Bearer $ADMIN" -d '{
"name": "ws-4812 copilot", "scope": "read",
"namespaces": ["ws-4812", "ws-4812-*"],
"cap_queries": 200000}'Questions
What is multi-tenant RAG?
Retrieval-augmented generation for an app with many customers: each customer’s copilot or assistant must retrieve only from that customer’s documents. The usual build is one vector index with a tenant_id filter on every query; SkimmerDB gives each customer a namespace of its own and keys that can only reach it.
Why not one index with a tenant_id filter?
It works until a query forgets the filter, and then one customer sees another’s data. With a namespace per customer and a key per namespace, isolation doesn’t depend on every code path being right. Deleting a customer is deleting a namespace, and a large customer doesn’t make everyone else’s index bigger.
How many namespaces can I have?
Unlimited on pro; the free plan allows 1,000. An idle namespace is under a kilobyte of bookkeeping plus its documents in object storage, and runs no compute, so a long tail of quiet customers costs what they store.
Who writes the data, my backend or the agent?
Usually your backend, through the REST API, the Python and TypeScript clients, or bulk imports of CSV, NDJSON and Parquet. The copilot only needs a read key. Agents that should save things (notes, memories) can get a write key limited to their namespace.
Can I see what each customer uses?
Listing namespaces gives each one’s stored bytes and the documents and bytes written to it, and every query answer reports its latency, cache temperature, object-store reads and CPU, so you can attribute cost per customer. Key caps limit what each customer’s key can do in a billing period.
What does a quiet customer cost?
Only its storage: $0.10 per GB-month on pro, and the free plan includes 1 GB. Its first query after a long sleep reads from object storage in a round trip or two, then it’s warm.
Give every customer their own index
Free up to 1 GB stored and 100k queries a month. No card to start.