Skip to main content

Multi-Tenancy

SynapseX provides complete multi-tenant architecture for B2B applications, enabling customer isolation, per-tenant customization, and centralized management.

Overview​

Multi-tenancy in SynapseX means:

  • Data Isolation - Each tenant's data is completely separated
  • Custom Models - Per-tenant LoRA adapters and configurations
  • Independent Rate Limits - Separate quotas per customer
  • Billing Separation - Track usage per tenant
  • API Key Management - Unique keys per tenant
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MULTI-TENANT ARCHITECTURE β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Tenant A β”‚ β”‚ Tenant B β”‚ β”‚ Tenant C β”‚ β”‚ Tenant D β”‚ β”‚
β”‚ β”‚ Pharmacy β”‚ β”‚ Hospital β”‚ β”‚ Retailer β”‚ β”‚ Bank β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ X-Tenant-ID β”‚ X-Tenant-ID β”‚ X-Tenant-ID β”‚ X-Tenant-ID β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β–Ό β–Ό β–Ό β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ SYNAPSEX API GATEWAY β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β€’ Authenticate tenant β”‚ β”‚
β”‚ β”‚ β€’ Apply rate limits β”‚ β”‚
β”‚ β”‚ β€’ Route to tenant context β”‚ β”‚
β”‚ β”‚ β€’ Load tenant LoRA β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β–Ό β–Ό β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Tenant A β”‚ β”‚ Tenant B β”‚ β”‚ Tenant C β”‚ β”‚
β”‚ β”‚ Context β”‚ β”‚ Context β”‚ β”‚ Context β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β€’ LoRA v3 β”‚ β”‚ β€’ LoRA v5 β”‚ β”‚ β€’ LoRA v2 β”‚ β”‚
β”‚ β”‚ β€’ RAG docs β”‚ β”‚ β€’ RAG docs β”‚ β”‚ β€’ RAG docs β”‚ β”‚
β”‚ β”‚ β€’ Settings β”‚ β”‚ β€’ Settings β”‚ β”‚ β€’ Settings β”‚ β”‚
β”‚ β”‚ β€’ Feedback β”‚ β”‚ β€’ Feedback β”‚ β”‚ β€’ Feedback β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tenant Management​

Create Tenant​

import requests

response = requests.post(
"https://api.synapsex.ai/v1/tenants",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"name": "FarmΓ‘cia Santa Casa",
"slug": "farmacia_santa_casa",
"tier": "pro",
"contact_email": "admin@farmacia.com",
"settings": {
"default_model": "synapsex-chat",
"max_tokens_per_request": 2048,
"enable_rerank": True,
"rerank_tier": "quantum_cpu",
"custom_system_prompt": "You are a pharmacy assistant for FarmΓ‘cia Santa Casa."
}
}
)

tenant = response.json()
print(f"Tenant ID: {tenant['id']}")
print(f"API Key: {tenant['api_key']}")

Tenant Tiers​

TierRate LimitTokens/DayFeatures
free20 req/min10,000Basic
pro100 req/min100,000+ Quantum CPU
business500 req/min1,000,000+ Training
enterpriseCustomUnlimited+ Quantum GPU, SLA

List Tenants​

response = requests.get(
"https://api.synapsex.ai/v1/tenants",
headers={"Authorization": "Bearer sk-admin-xxx"},
params={"tier": "pro", "limit": 50}
)

for tenant in response.json()['tenants']:
print(f"{tenant['name']} ({tenant['slug']}): {tenant['tier']}")

Update Tenant​

response = requests.patch(
"https://api.synapsex.ai/v1/tenants/tenant_abc123",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"tier": "business",
"settings": {
"rerank_tier": "quantum_gpu"
}
}
)

Delete Tenant​

response = requests.delete(
"https://api.synapsex.ai/v1/tenants/tenant_abc123",
headers={"Authorization": "Bearer sk-admin-xxx"}
)

Tenant Authentication​

Using Tenant API Key​

Each tenant gets a unique API key:

from openai import OpenAI

# Tenant-specific client
client = OpenAI(
api_key="sk-farmacia-santa-casa-xxx", # Tenant's API key
base_url="https://api.synapsex.ai/v1"
)

response = client.chat.completions.create(
model="synapsex-chat",
messages=[{"role": "user", "content": "What medications interact with aspirin?"}]
)

Using X-Tenant-ID Header​

For platform-level access with tenant routing:

response = requests.post(
"https://api.synapsex.ai/v1/chat/completions",
headers={
"Authorization": "Bearer sk-platform-xxx", # Platform key
"X-Tenant-ID": "farmacia_santa_casa" # Route to tenant
},
json={
"model": "synapsex-chat",
"messages": [{"role": "user", "content": "..."}]
}
)

Tenant Settings​

Configuration Options​

response = requests.patch(
"https://api.synapsex.ai/v1/tenants/tenant_abc/settings",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
# Model settings
"default_model": "synapsex-chat-32k",
"max_tokens_per_request": 4096,
"default_temperature": 0.7,

# Reranking
"enable_rerank": True,
"rerank_tier": "quantum_cpu",
"rerank_k": 4,

# Custom behavior
"custom_system_prompt": "You are a helpful assistant for...",
"allowed_topics": ["healthcare", "products", "orders"],
"blocked_topics": ["competitors", "legal_advice"],

# RAG
"enable_rag": True,
"rag_top_k": 5,
"rag_threshold": 0.7,

# Rate limits (overrides tier defaults)
"rate_limit_rpm": 150,
"daily_token_limit": 500000
}
)

Get Settings​

response = requests.get(
"https://api.synapsex.ai/v1/tenants/tenant_abc/settings",
headers={"Authorization": "Bearer sk-admin-xxx"}
)

settings = response.json()
print(f"Model: {settings['default_model']}")
print(f"Rerank: {settings['rerank_tier']}")

Per-Tenant RAG​

Upload Documents​

# Register dataset for tenant
response = requests.post(
"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/datasets/register",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"name": "product_catalog",
"type": "documents",
"data_use": {"allow_rag": True}
}
)

dataset_id = response.json()['id']

# Upload documents
response = requests.post(
f"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/datasets/{dataset_id}/upload/docs",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"docs": [
{
"doc_id": "med_001",
"title": "Aspirin 500mg",
"text": "Pain reliever and anti-inflammatory. Dosage: 1-2 tablets every 4-6 hours...",
"metadata": {"category": "analgesics", "price": 12.99}
}
]
}
)

RAG in Action​

When the tenant makes a request:

# Tenant request
response = client.chat.completions.create(
model="synapsex-chat",
messages=[{"role": "user", "content": "What pain medications do you have?"}]
)

# Response includes RAG context automatically
print(response.choices[0].message.content)
# "We have several pain medications including Aspirin 500mg ($12.99)..."

Per-Tenant LoRA​

Training Flow​

  1. Collect feedback from tenant users
  2. Trigger training when threshold reached
  3. Deploy LoRA adapter for tenant
  4. Automatic loading on inference
# Check training readiness
response = requests.get(
"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/feedback/stats",
headers={"Authorization": "Bearer sk-admin-xxx"}
)

if response.json()['ready_for_training']:
# Trigger training
response = requests.post(
"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/train/lora",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={"epochs": 3, "lora_r": 16}
)
print(f"Training job: {response.json()['job_id']}")

LoRA Loading​

When a request comes in for a tenant:

1. Request arrives with X-Tenant-ID: farmacia_santa_casa
2. System loads base model + farmacia_santa_casa LoRA adapter
3. Response generated with tenant-specific adaptations
4. LoRA unloaded (or cached for next request)

Usage Tracking​

Get Tenant Usage​

response = requests.get(
"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/usage",
headers={"Authorization": "Bearer sk-admin-xxx"},
params={"period": "current_month"}
)

usage = response.json()
print(f"Requests: {usage['requests']}")
print(f"Tokens: {usage['tokens']}")
print(f"Rerank calls: {usage['rerank_calls']}")
print(f"Training jobs: {usage['training_jobs']}")

Usage by Day​

response = requests.get(
"https://api.synapsex.ai/v1/tenants/farmacia_santa_casa/usage/daily",
headers={"Authorization": "Bearer sk-admin-xxx"},
params={"from": "2024-01-01", "to": "2024-01-31"}
)

for day in response.json()['days']:
print(f"{day['date']}: {day['requests']} requests, {day['tokens']} tokens")

All Tenants Usage​

response = requests.get(
"https://api.synapsex.ai/v1/admin/usage/tenants",
headers={"Authorization": "Bearer sk-admin-xxx"},
params={"period": "current_month", "sort": "tokens_desc"}
)

for tenant in response.json()['tenants']:
print(f"{tenant['name']}: {tenant['tokens']:,} tokens")

Billing Integration​

Webhook for Usage​

Configure webhooks for billing integration:

response = requests.post(
"https://api.synapsex.ai/v1/webhooks",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"url": "https://your-billing-system.com/webhook",
"events": ["usage.daily", "usage.limit_reached"],
"secret": "webhook-secret"
}
)

Usage Webhook Payload​

{
"event": "usage.daily",
"timestamp": "2024-01-15T00:00:00Z",
"data": {
"tenant_id": "tenant_abc123",
"tenant_slug": "farmacia_santa_casa",
"period": "2024-01-14",
"metrics": {
"requests": 1500,
"tokens": 450000,
"rerank_calls": 1200,
"quantum_rerank_calls": 800
}
}
}

Self-Service Trial​

Enable customers to self-onboard:

Trial Configuration​

response = requests.post(
"https://api.synapsex.ai/v1/admin/trial/config",
headers={"Authorization": "Bearer sk-admin-xxx"},
json={
"enabled": True,
"duration_days": 14,
"limits": {
"requests_per_day": 100,
"tokens_per_day": 10000
},
"features": {
"rerank_tier": "classic",
"enable_rag": True,
"enable_training": False
}
}
)

Trial Signup Endpoint​

POST /public/trial/signup
{
"email": "customer@company.com",
"company_name": "Acme Corp",
"use_case": "Customer support automation"
}

Response:

{
"tenant_id": "trial_xyz789",
"api_key": "sk-trial-xyz789-xxx",
"expires_at": "2024-01-29T00:00:00Z",
"limits": {
"requests_per_day": 100,
"tokens_per_day": 10000
}
}

Best Practices​

Security​

βœ… Do:

  • Use tenant-specific API keys
  • Validate X-Tenant-ID on all requests
  • Implement IP whitelisting for enterprise
  • Audit tenant data access

❌ Don't:

  • Share API keys between tenants
  • Allow cross-tenant data access
  • Store tenant secrets in logs

Performance​

βœ… Do:

  • Cache tenant settings
  • Pre-load frequently used LoRAs
  • Use connection pooling per tenant
  • Set appropriate rate limits

❌ Don't:

  • Load LoRA on every request
  • Allow unlimited token consumption
  • Skip tenant validation

Next Steps​