> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hydradb.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> AGENTS.md is HydraDB's maintained agent guide. Read https://docs.hydradb.com/AGENTS.md once, then use its content. /llms.txt and /llms-full.txt redirect to the same guide; they are not separate documentation indexes. If the guide is already loaded, continue with it instead of fetching either alias or reloading the guide.

# Databases and Collections

> Scope every write and read with a database and a collection, and split scopes only where context must never meet in one query.

HydraDB scopes every write and every read with two fields: `database`, an isolated store for one customer or one environment, and `collection`, an optional group inside a database. Most products need one database and one collection. Your backend sets both on every request; the user never chooses them.

## 1. Choose how to scope your data

Pick the scope by what must never meet in one query:

| Goal | Use |
| - | - |
| A company brain: one query across all your files and connectors | One `database` and one collection for everything. Isolate results inside it with metadata filters and access control |
| Separate customers on your platform | A different `database` per customer |
| Separate environments (`prod` vs `staging`) | A different `database` per environment |
| Keep each person's memories apart | One `database`, and a collection per person, such as `user_123` |

### Company brain

Put everything in one collection: connect all your connectors and ingest all your files and app sources there, so one query searches across all of it. When some results must stay out of reach for some people, keep the single collection and isolate inside it. Put a team, region, or user ID in [metadata](https://docs.hydradb.com/essentials/v2/metadata.md) and filter on it. Let [access control](https://docs.hydradb.com/essentials/v2/query.md#6-query-on-behalf-of-a-user), captured from the source app's permissions or set by you, decide who may retrieve each source. HydraDB enforces both inside one query.

### B2C application

Use one database for the application. Keep shared knowledge in one collection, and give each user a collection for their memories, for example `collection = "user_123"`. Ingest each user's preferences and conversation history with that collection, and query with the same one.

### B2B SaaS

Use one database per customer organization, for example `database = "acme_corp"`. Inside it, keep the organization's knowledge in one collection and isolate teams with metadata filters and access control. Give each user a collection only for their memories.

### Shared knowledge plus personal memories

For answers grounded in shared knowledge and personalized with the user's memories, send `type: "all"` on [`POST /query`](https://docs.hydradb.com/api-reference/v2/endpoint/query). It reads both from the same collections and returns one ranked list, so name the knowledge collection and the user's with `collections: ["company_docs", "user_123"]`. Every listed collection must already exist, and the list holds up to 100. When your prompt needs the two formatted differently, call `POST /query` twice, once with `type: "knowledge"` and once with `type: "memory"`.

## 2. Write and read with the same scope

This example saves a memory for `user_123` and then queries it for the same user. Both requests name the database `acme_corp` and the collection `user_123`. That is the whole mechanism: context written under a collection is read back only by requests that name that collection.

> [accordion] Save a memory and query it with the same scope: Python, TypeScript, or cURL
>
> Set up your [SDK client](https://docs.hydradb.com/api-reference/v2/sdks.md#client-setup) before running the Python or TypeScript example.
>
> ```python Python SDK theme={"dark"}
> import json
> import os
> from hydra_db import HydraDB
>
> client = HydraDB(token=os.environ["HYDRADB_API_KEY"])
>
> # 1. Write a memory under the user's collection.
> client.context.ingest(
>     type="memory",
>     database="acme_corp",
>     collection="user_123",
>     memories=json.dumps([
>         {
>             "text": "Prefers dark mode and short answers.",
>             "infer": True,
>             "user_name": "John",
>         }
>     ]),
> )
> ```
>
> ```typescript TypeScript SDK theme={"dark"}
> import { HydraDBClient } from "@hydradb/sdk";
>
> const client = new HydraDBClient({
>   token: process.env.HYDRADB_API_KEY,
> });
>
> // 1. Write a memory under the user's collection.
> await client.context.ingest({
>   type: "memory",
>   database: "acme_corp",
>   collection: "user_123",
>   memories: JSON.stringify([
>     {
>       text: "Prefers dark mode and short answers.",
>       infer: true,
>       user_name: "John",
>     },
>   ]),
> });
> ```
>
> ```bash cURL theme={"dark"}
> # 1. Write a memory under the user's collection.
> curl -X POST 'https://api.hydradb.com/context/ingest' \
>   -H "Authorization: Bearer $HYDRADB_API_KEY" \
>   -H "API-Version: 2" \
>   -F "type=memory" \
>   -F "database=acme_corp" \
>   -F "collection=user_123" \
>   -F 'memories=[
>     {
>       "text": "Prefers dark mode and short answers.",
>       "infer": true,
>       "user_name": "John"
>     }
>   ]'
> ```
>
> Wait for [`GET /context/status`](https://docs.hydradb.com/api-reference/v2/endpoint/source-status) to report `completed` for the returned memory `id` in `user_123`, then run the query.
>
> ```python Python SDK theme={"dark"}
> # 2. Search the memories in the same collection.
> result = client.query(
>     database="acme_corp",
>     collection="user_123",
>     query="How does this user like answers written?",
>     type="memory",
> )
> ```
>
> ```typescript TypeScript SDK theme={"dark"}
> // 2. Search the memories in the same collection.
> const result = await client.query({
>   database: "acme_corp",
>   collection: "user_123",
>   query: "How does this user like answers written?",
>   type: "memory",
> });
> ```
>
> ```bash cURL theme={"dark"}
> # 2. Search the memories in the same collection.
> curl -X POST 'https://api.hydradb.com/query' \
>   -H "Authorization: Bearer $HYDRADB_API_KEY" \
>   -H "API-Version: 2" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "database": "acme_corp",
>     "collection": "user_123",
>     "query": "How does this user like answers written?",
>     "type": "memory"
>   }'
> ```

### What each property means

| Property | What it is |
| - | - |
| `database` | The customer's or environment's database. Create it first with [`POST /databases`](https://docs.hydradb.com/api-reference/v2/endpoint/create-database). |
| `collection` | The group inside the database. Both requests name the same one, so the query reads what the write stored. |
| `type` | `memory` on both: the write saves a [memory](https://docs.hydradb.com/essentials/v2/context.md#2-save-memories) and the query searches memories. `knowledge` and `all` work the same way with the same scope. |
| `memories` | The memory items, as a JSON string. |
| `query` | The user's question. HydraDB ranks results inside the collection you named. |

Use stable internal IDs for both fields, such as `user_123`, `workspace_42`, or `org_acme`. Display names, emails, and user-typed labels change, and a changed scope name orphans the context written under the old one.

## 3. How writes and reads scope

**Writes:** Send the `collection` you will query the context from. John's memories go in John's collection; shared knowledge goes in the shared one. Omit `collection` and HydraDB uses the database's default collection, which is created on the first write.

**Reads:** A query that names one `collection` reads only that collection. It does not read the default collection or any other collection. To read several at once, send `collections` as a list, or as an object that maps each collection to a relative ranking weight, as in `{"company_docs": 1.5, "user_123": 0.8}`.

**Deleting a collection:** [`DELETE /databases/collections`](https://docs.hydradb.com/api-reference/v2/endpoint/delete-collection) permanently removes one collection and everything in it. The parent database and its other collections stay. Confirm the name with [List Collections](https://docs.hydradb.com/api-reference/v2/endpoint/list-collections.md) first. On the dashboard, open a database to see its collections and delete from the list.

## 4. Migrate from the deprecated tenant and sub-tenant fields

`database` and `collection` are the current names for the fields that were called `tenant_id` and `sub_tenant_id`. The rename is user-facing only. Nothing about your stored context changes, the old names still work as deprecated aliases, and migration is optional and non-breaking.

Both names work on every surface:

| Surface | Deprecated (still works) | Current (preferred) |
| - | - | - |
| Routes | `/tenants`, `/tenants/status`, `/tenants/{tenant_id}/metadata-schema`, and the rest | `/databases`, `/databases/status`, `/databases/{database}/metadata-schema`, and the rest |
| Request fields | `tenant_id`, `sub_tenant_id` | `database`, `collection` |
| `/query` multi-scope selector | `sub_tenant_ids` | `collections` |
| Query params | `?tenant_id=...&sub_tenant_id=...` | `?database=...&collection=...` |

Both route prefixes use the same handlers. Deprecated fields are accepted in the query string, the JSON body, and the multipart form. The singular `sub_tenant_id` still works on [`/query`](https://docs.hydradb.com/api-reference/v2/endpoint/query) too.

### Deprecation signals

When a request uses a deprecated route or field, HydraDB adds a deprecation notice. It is never an error, and the status code is unchanged:

* **Response headers:** `Deprecation: true`, plus a `Warning` header carrying the migration message.
* **`meta.deprecation`:** a list of notices in the response envelope's `meta` object, on endpoints that return the envelope. Each entry carries `deprecated`, a readable `message`, and `deprecated_since` (`"2.0.1"`). Field-level notices, such as `sub_tenant_ids` to `collections`, also include `deprecated_field` and `preferred_field`; route-level notices omit them.

> [accordion] Response envelope with a deprecation notice
>
> ```json theme={"dark"}
> {
>   "success": true,
>   "data": { "...": "..." },
>   "error": null,
>   "meta": {
>     "request_id": "9d13aef4-02f4-4e73-8c62-4c2601d04f9d",
>     "latency_ms": 12.3,
>     "deprecation": [
>       {
>         "deprecated": true,
>         "message": "The /tenants routes are deprecated. Migrate to the /databases routes.",
>         "deprecated_since": "2.0.1"
>       }
>     ]
>   }
> }
> ```

Use these signals to find and retire deprecated usage. Once you send only the current names on the `/databases` routes, the header and `meta.deprecation` disappear.

### Sending both names

If you send a current field and its deprecated alias together:

* **Same value:** for example `database` and `tenant_id` both `"acme"`. Accepted. HydraDB uses the current field.
* **Different values:** for example `database: "acme"` and `tenant_id: "other"`. Rejected with `400`, because the two names refer to the same thing and must agree. Send only one. The same rule applies to `collection` and `sub_tenant_id`, and to `collections` and `sub_tenant_ids` on `/query`.

## Common mistakes

**Mismatched `collection` between write and read:**
Context written under one collection does not surface when queried under another. Use the same `collection` for the same logical scope on every call.

**Sharing a `database` across environments:**
Do not use one database for both production and staging. Create a database per environment.

**Confusing `database` with `collection`:**
Use `database` for primary boundaries such as customers or environments. Use `collection` for groups inside a database, such as users or workspaces.

**Writing shared knowledge under a user's collection by accident:**
Knowledge written with one user's `collection` is invisible to every other user. Choose the write scope from where it should be queried later.

## Related

* [Context](https://docs.hydradb.com/essentials/v2/context.md#2-save-memories): preferences, decisions, and past conversations
* [Query](https://docs.hydradb.com/essentials/v2/query.md): how scoping is applied at query time
* [Databases API](https://docs.hydradb.com/api-reference/v2/endpoint/databases-overview.md): creating databases and their metadata schema


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.