Skip to content

Multi-Tenancy

Backflow supports complete tenant isolation with per-tenant configurations.

Overview

Multi-tenancy allows:

  • Separate configurations per tenant
  • Isolated data and resources
  • Per-tenant rate limits
  • Tenant-specific integrations
  • Usage tracking per tenant
  • Hierarchical apps (sub-tenants)
  • Custom domains per tenant

Tenant Identification

Via Header

bash
curl -X GET http://localhost:3000/api/data \
  -H "Authorization: Bearer <token>" \
  -H "X-Tenant-ID: tenant-123"

Via JWT Claim

json
{
  "sub": "user-123",
  "tenant_id": "tenant-123",
  "role": "admin"
}

Tenant Configuration

Get Config

bash
GET /tenant/config
X-Tenant-ID: tenant-123

Set Config

bash
POST /tenant/config
X-Tenant-ID: tenant-123
Content-Type: application/json

{
  "routes": [...],
  "credentials": {...},
  "rateLimit": {...}
}

Tenant Routes

Each tenant can have custom routes:

json
{
  "routes": [
    {
      "path": "/custom-endpoint",
      "method": "get",
      "description": "Tenant-specific endpoint",
      "supabaseQueries": [{
        "table": "tenant_data",
        "operation": "select"
      }]
    }
  ]
}

Tenant Integrations

Per-tenant API credentials using secret references:

json
{
  "credentials": {
    "stripe": {
      "secretKey": "&#123;&#123;secret:stripe_key&#125;&#125;"
    },
    "jira": {
      "baseUrl": "https://tenant.atlassian.net",
      "email": "&#123;&#123;secret:jira_email&#125;&#125;",
      "apiToken": "&#123;&#123;secret:jira_token&#125;&#125;"
    }
  }
}

Security

Always use &#123;&#123;secret:key&#125;&#125; references instead of hardcoding credentials. Secrets are encrypted and isolated per tenant.

Rate Limits

Per-tenant rate limiting:

json
{
  "rateLimit": {
    "enabled": true,
    "default": {
      "windowMs": 60000,
      "max": 1000
    }
  }
}

Secrets Management

Tenant secrets provide secure, isolated storage for API keys and credentials with double encryption. See Tenant Secrets Reference for complete documentation.

Store Secret

bash
POST /tenant/secrets
Authorization: Bearer <token>

{
  "key": "stripe_key",
  "value": "sk_live_...",
  "metadata": { "provider": "stripe" }
}

Reference in Config

Use &#123;&#123;secret:key_name&#125;&#125; syntax to reference stored secrets:

json
{
  "credentials": {
    "stripe": {
      "secretKey": "&#123;&#123;secret:stripe_key&#125;&#125;"
    }
  }
}

Usage Tracking

Get Usage

bash
GET /usage/summary
X-Tenant-ID: tenant-123

Response:

json
{
  "tenant_id": "tenant-123",
  "period": "2024-01",
  "api_calls": 15420,
  "llm_tokens": 250000,
  "storage_bytes": 1073741824
}

Tenant Endpoints

MethodEndpointDescription
GET/tenant/configGet tenant config
POST/tenant/configSave tenant config
GET/tenant/secretsList secret keys
POST/tenant/secretsStore secret
DELETE/tenant/secrets/:keyDelete secret

Data Isolation

Queries automatically filter by tenant:

json
{
  "table": "orders",
  "operation": "select",
  "filters": [
    {
      "column": "tenant_id",
      "operator": "eq",
      "value": "&#123;&#123;tenant.id&#125;&#125;"
    }
  ]
}

Dynamic Routes

Tenant routes are registered dynamically:

  1. Tenant saves config via /tenant/config
  2. Routes are validated
  3. Routes become available at tenant-prefixed paths
  4. Requests route to tenant-specific handlers

Apps (Sub-Tenants)

Tenants can create child tenants (apps) for isolated environments.

List Apps

bash
GET /tenant/apps
Authorization: Bearer <token>
X-Tenant-ID: parent-tenant-123

Response:

json
{
  "apps": [
    {
      "id": "parent-tenant-123_abc123",
      "name": "Production",
      "parentTenantId": "parent-tenant-123",
      "planTier": "free",
      "createdAt": "2024-01-15T10:00:00Z",
      "isActive": true
    }
  ]
}

Create App

bash
POST /tenant/apps
Authorization: Bearer <token>
X-Tenant-ID: parent-tenant-123
Content-Type: application/json

{
  "name": "Staging Environment",
  "config": {
    "environment": "staging"
  }
}

Delete App

bash
DELETE /tenant/apps/{appId}
Authorization: Bearer <token>
X-Tenant-ID: parent-tenant-123

SDK Usage

typescript
// List apps
const apps = await bf.tenant.apps.list();

// Create app
const app = await bf.tenant.apps.create('Production', { environment: 'prod' });

// Delete app
await bf.tenant.apps.delete('app-id');

Use Cases

  • Environment isolation: Separate dev/staging/prod configs
  • Client isolation: Create apps per client for SaaS
  • Feature flags: Test features in isolated environments

Custom Domains

Configure custom domains for your tenant's API.

Default Domain

Every tenant gets a default subdomain:

{tenant-slug}.api.backflow.dev

List Domains

bash
GET /tenant/domains
Authorization: Bearer <token>
X-Tenant-ID: tenant-123

Add Domain

bash
POST /tenant/domains
Authorization: Bearer <token>
X-Tenant-ID: tenant-123
Content-Type: application/json

{
  "domain": "api.mycompany.com",
  "type": "primary"
}

Response includes verification instructions:

json
{
  "domain": {
    "domain": "api.mycompany.com",
    "type": "primary",
    "verified": false,
    "sslStatus": "pending"
  },
  "verificationInstructions": {
    "method": "dns",
    "domain": "api.mycompany.com",
    "dnsRecord": {
      "type": "TXT",
      "name": "_backflow.api.mycompany.com",
      "value": "bf-verify-abc123xyz"
    }
  }
}

Verify Domain

After adding the DNS record:

bash
POST /tenant/domains/{domain}/verify
Authorization: Bearer <token>
X-Tenant-ID: tenant-123

SDK Usage

typescript
// List domains
const domains = await bf.tenant.domains.list();

// Add domain
const result = await bf.tenant.domains.add('api.mycompany.com', 'primary');
console.log(result.verificationInstructions);

// Verify domain
const { verified } = await bf.tenant.domains.verify('api.mycompany.com');

// Get verification instructions
const instructions = await bf.tenant.domains.getVerificationInstructions('api.mycompany.com');

// Remove domain
await bf.tenant.domains.remove('api.mycompany.com');

Best Practices

  1. Always include X-Tenant-ID header
  2. Store sensitive credentials as secrets
  3. Set appropriate rate limits per tenant
  4. Monitor usage with analytics endpoints
  5. Use tenant-specific database tables or RLS
  6. Use apps for environment isolation
  7. Verify custom domains before production use

Released under the ISC License.