Skip to main content

1. What it is

HydraDB scopes data using two identifiers:
  • tenant_id - the top-level scoping identifier. Use it for customers, environments, or other primary data boundaries.
  • sub_tenant_id - an optional scoping identifier within a tenant. Use it for users, workspaces, teams, or other logical partitions.
HydraDB write and recall operations are scoped by tenant_id. When sub_tenant_id is provided, it further narrows the scope for that operation. If you omit sub_tenant_id, HydraDB uses the tenant’s default sub-tenant. Use the same scoping values consistently across writes and reads. If you write data with one sub_tenant_id and later recall with a different one, that data may not appear in the recall results.

2. When to use each

Two practical rules:
  • Use a separate tenant whenever data must not mix across customers or environments.
  • Use a sub-tenant for logical partitions inside a tenant, such as users, workspaces, teams, or projects.
Do not use sub_tenant_id as a substitute for separate production and staging tenants. Environments should usually be separated at the tenant_id level.

B2C application

Use one tenant for the application or customer account, and use each end-user as a sub-tenant.
Use this when each user has private Memories, preferences, or conversation history. Typical flow:
  • Write user Memories with sub_tenant_id = user_id.
  • Recall user Memories with the same sub_tenant_id.
  • Keep shared Knowledge outside the user-specific scope.

B2B SaaS

Use one tenant per customer organization. Use sub_tenant_id for the workspace, team, project, or user scope inside that customer.
Typical flow:
  • Customer-level Knowledge uses the customer tenant_id.
  • Workspace-specific data uses a workspace sub_tenant_id.
  • User-specific Memories use a user-level sub_tenant_id.

Shared Knowledge + user personalization

For personalized answers grounded in shared Knowledge, keep the two retrieval paths explicit:
  • Use full_recall for shared Knowledge - this hits the Knowledge vector store (vectorstore_status index 1).
  • Use recall_preferences for user-specific Memories - this hits the Memories vector store (vectorstore_status index 0).
  • Merge the two results in your application before prompting the LLM.
This mirrors the pattern used throughout the Recall and Memories pages: shared context and personal context are retrieved separately, then combined at prompt time.

4. How scoping works

Writes

Writes include tenant_id, and may include sub_tenant_id. Use sub_tenant_id when the data belongs to a specific user, workspace, team, or other logical partition. Omit it when you intentionally want the data written to the tenant’s default sub-tenant. Examples:
  • A memory about John’s preferences should be written with John’s sub_tenant_id.
  • Workspace-specific runbooks should be written with that workspace’s sub_tenant_id.
  • Broadly shared Knowledge should use the same scope you plan to use when recalling it.

Reads

Recall requests include tenant_id, and may include sub_tenant_id. If sub_tenant_id is omitted, recall uses the tenant’s default sub-tenant. Use the same scoping values on recall that you used when writing the data. A recall request with one sub_tenant_id should not be expected to retrieve data written under a different sub_tenant_id. If your application needs to combine data from multiple scopes, make separate recall calls and merge the results in your application. Use sub_tenant_id for partitioning data. Use metadata_filters for narrowing results within that scope.

Memories and Knowledge

Memory recall and Knowledge recall are separate retrieval paths:
  • recall_preferences retrieves Memories (user-scoped, personal).
  • full_recall retrieves Knowledge (shared documents and app sources).
For a personalized answer, a common pattern is:
  1. Recall shared Knowledge with full_recall.
  2. Recall user Memories with recall_preferences.
  3. Format and merge both results into one LLM prompt.

Data written under one sub-tenant should not be expected to appear when recalling from another. Keep scope identifiers stable and consistent in your application.


5. Minimal working example

The example below shows a common personalized-answer flow: write a user Memory, recall that user’s preferences, recall shared Knowledge, and merge the two contexts in your application.

6. Common mistakes

Mismatched sub_tenant_id between write and read. Data written under one sub-tenant should not be expected to surface when recalled under another. Use the same sub_tenant_id consistently for the same logical scope. Sharing a tenant_id across environments. Do not use one tenant for both production and staging. Create separate tenants for separate environments. Confusing tenant_id with sub_tenant_id. Use tenant_id for primary boundaries such as customers or environments. Use sub_tenant_id for partitions inside a tenant, such as users or workspaces. Assuming recall automatically merges scopes. A recall call uses the scope you provide. If your application needs data from multiple scopes, make multiple calls and merge the results yourself. Writing shared Knowledge under a user scope by accident. If broadly shared Knowledge is written with a user-specific sub_tenant_id, it may not appear where other users expect it. Choose the write scope based on where the content should be recalled later. Using metadata filters as a substitute for sub-tenants. Metadata filters narrow results inside a scope. They are not a replacement for choosing the right tenant_id and sub_tenant_id. Using unstable identifiers. Avoid display names, emails that may change, or user-provided labels as long-term scope identifiers. Prefer stable internal IDs such as user_123, workspace_42, or org_acme.