--- title: "Multi-tenancy overview" sidebarTitle: "Overview" description: "How Supermemory isolates and organizes memories across users, tenants, and projects" icon: "/icons/hugeicons/user-multiple.svg" --- Most apps built on Supermemory serve more than one user, customer, or tenant out of a single Supermemory organization. Multi-tenancy is how you keep those memories apart — so User A's data is never visible to User B, and so you can still slice and query within a user's own data by things like category, status, or date. Supermemory gives you two complementary tools for this: **Isolation.** A namespace is a hard boundary. Memories in one namespace are never returned by a search scoped to another namespace. **Organization.** Metadata is a set of custom key/value properties on a memory that you filter by — category, priority, date, participants, anything you define. They solve different problems, and most production apps use both together. --- ## Why two mechanisms It's tempting to reach for one tool and make it do everything, but namespaces and metadata aren't interchangeable — they answer different questions. | Question | Answer | |----------|--------| | "Which tenant does this memory belong to?" | **Namespace** | | "Within this tenant's memories, which ones match `status: open`?" | **Metadata filter** | | "Can this API key even see tenant X's data?" | **Namespace** (enforced as an access boundary) | | "Find memories tagged `engineering` created after March" | **Metadata filter** | A namespace decides **whether a memory is reachable at all** for a given request. Metadata decides **which of the reachable memories match**. Filtering never crosses a namespace boundary — you can't use metadata to peek into another tenant's namespace. --- ## How they work together A typical multi-tenant write scopes the memory to a tenant with a namespace, then attaches metadata for finer-grained querying later: ```typescript await supermemory.add("org_acme", { // isolates to the "acme" tenant content: "Customer requested a refund for order #4821", metadata: { category: "support", status: "open", priority: "high", }, }); ``` And a search combines both: the namespace restricts *which tenant's data* is in scope, and the filter narrows down *which memories within that tenant* come back: ```typescript const results = await supermemory.search("org_acme", { query: "refund request", filter: { operator: "and", operands: [ { field: "category", operator: "eq", value: "support" }, { field: "status", operator: "eq", value: "open" }, ], }, searchMode: "chunks", }); ``` The namespace is **required** on every call (it is part of the URL) and validated as an access boundary. Metadata filters are **optional** — a search with just `namespace` and no `filter` still only returns that tenant's memories. --- ## Choosing your boundary The namespace is the layer that should map to your actual tenancy model — pick the level that matches what "one isolated space" means in your app: | Pattern | Example | Use case | |---------|---------|----------| | Per-user | `user_{userId}` | Consumer app, personal memory per user | | Per-tenant/org | `org_{orgId}` | B2B SaaS, one namespace per customer org | | Hierarchical | `org:{orgId}:user:{userId}` | Multi-level — isolate by org, and optionally drill into a user within it | | Per-project | `project_{projectId}` | Workspace- or project-scoped content | The simplest form is one namespace per user, derived from an ID you already have: ```typescript await supermemory.add(userId, { // one namespace per user content: "User prefers morning workouts", }); const results = await supermemory.search(userId, { query: "workout preferences", }); ``` Everything *within* that boundary — categories, statuses, dates, custom fields — is metadata, not a new namespace. Don't create a new namespace for every property you want to filter on; that's what metadata is for. --- ## Access control Namespaces aren't just organizational — they're enforced as an authorization boundary. API keys and org members can be restricted to specific namespaces, so a request for a namespace outside the caller's allowed set is rejected with `403 Forbidden` rather than silently filtered. See [Namespaces → Access control](/concepts/container-tags#access-control) for the details. --- ## Next steps Personal agents, company agents, email assistants, and support platforms. How isolation works, naming rules, and access control. Metadata filter operators, combining `and`/`or`, and query limits. Mint keys that can only touch one namespace.