Multi-Tenant Architecture
Build SaaS applications on top of HyperSpark Memory with complete data isolation, unified billing, and a single API key for all your customers.
Organization Hierarchy
HyperSpark Memory uses a flat two-level hierarchy: your organization (parent) contains multiple tenant organizations (your customers).
Key Concepts
Parent Organization
Your developer account that owns all tenants. Your API key and billing are tied to this organization.
Tenant Organization
An isolated memory store for one of your customers. Each tenant has completely separate data.
Data Isolation
Each tenant's memories are completely isolated. Cross-tenant queries are impossible by design.
Billing Rollup
All usage from all tenants counts against your parent org's plan. Simple, unified billing.
Organization Types
| Type | Description | When Set |
|---|---|---|
| standalone | Default for regular users with no tenants | Account creation |
| parent | Your org after creating your first tenant | First tenant creation |
| tenant | Customer organizations you create | Tenant creation |
Data Isolation Guarantees
Complete Isolation by Design
Every memory operation is scoped by organization ID. The database layer enforces isolation through row-level security policies, making cross-tenant access structurally impossible.
Each tenant's memories are stored with their organization_id. Queries automatically filter.
Your API key can access all tenants under your org, but not other parent orgs.
Attempts to access non-owned tenant IDs are rejected with 403 Forbidden.
Billing Model
All tenant usage rolls up to your parent organization. This means you pay for the total queries and memories across all your tenants.
Example: Usage Rollup
/api/v1/memory/stats?tenantId=... endpoint to track usage per tenant for your own billing purposes.Quick Start
// 1. Create a tenant for your customer
const response = await fetch('/api/v1/tenants', {
method: 'POST',
headers: {
'Authorization': 'Bearer hs_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Acme Corporation',
slug: 'acme-corp'
})
});
const { tenant, tenantId } = await response.json();
// tenantId = "org_abc123xyz"
// 2. Store memories for this tenant
await fetch('/api/v1/memory/ingest', {
method: 'POST',
headers: {
'Authorization': 'Bearer hs_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tenantId: 'org_abc123xyz', // Your customer's tenant
userId: 'user_123', // User within that tenant
messages: [
{ role: 'user', content: 'Our Q4 budget is $50,000' }
]
})
});
// 3. Query only this tenant's memories
const result = await fetch('/api/v1/memory/recall', {
method: 'POST',
headers: {
'Authorization': 'Bearer hs_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tenantId: 'org_abc123xyz',
userId: 'user_123',
query: 'budget information'
})
});Best Practices
Store tenant ID with customer records
Map your customer IDs to HyperSpark tenant IDs in your database for easy lookup.
Create tenants during customer onboarding
Automate tenant creation as part of your customer signup flow.
Clean up tenants on customer deletion
Delete the tenant when a customer leaves to remove all their data permanently.
Never expose your API key client-side
Your API key can access all tenants. Always use server-side routes.