Multi-Tenant SaaS Applications

HeliosDB Lite runs the data of a multi-tenant SaaS application in shared tables: each tenant gets its own database role, a row-level security policy compares a tenant column with current_user, and the same policy filters PostgreSQL wire sessions and REST requests, because a REST request runs as the role named in its token, so every tenant sees only its own records.

Superusers bypass row-level security; give each tenant its own non-superuser role and start the server with SCRAM authentication so clients cannot claim another role. Read the documentation.

Executive Summary

  • Zero operational complexity - no database management layer required

Problem Being Solved

The Multi-Tenancy Dilemma

SaaS platforms face a critical architectural trade-off:

Option A: Shared Database

  • Pro: Operational simplicity (single database)
  • Con: Catastrophic: Any tenant query can slow all tenants
  • Con: Catastrophic: Bugs/attacks affect all tenants
  • Con: Critical: Row-level security complex and fragile
  • Con: Data breach = all customer data compromised
  • Con: Noisy neighbor problem endemic

Option B: Database Per Tenant

  • Pro: True isolation (separate database per tenant)
  • Pro: Security: No cross-tenant contamination
  • Con: Catastrophic: Each tenant needs backup, monitoring, patching
  • Con: Scaling nightmare - managing hundreds of database instances
  • Con: Complex connection pooling across database fleet
  • Con: Retention policies, upgrades become operational burden

Enterprise Pain Points

Operational Burden:

  • Managing separate connection pools for each tenant
  • Setting up RLS (row-level security) policies in each database
  • Backup/restore procedures for each tenant separately
  • Scaling requires provisioning new instances (hours not minutes)

Security & Isolation Challenges:

  • Shared database RLS bugs expose all customer data
  • Connection pool misconfigurations leak tenant data between customers
  • Noisy neighbor: one tenant's bad queries slow all others
  • Audit trails mixed across all tenants

HeliosDB Lite Solution Architecture

Multi-Tenancy Isolation Model

Three-Layer Isolation Strategy:

┌─────────────────────────────────────────────────────────┐
│  Layer 1: Process Boundary Isolation                    │
│  ├─ Each tenant runs in separate database context       │
│  ├─ No shared memory with other tenants                 │
│  └─ Operating system enforces process boundaries        │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│  Layer 2: Cryptographic Branch Isolation                │
│  ├─ Each tenant database = unique branch                │
│  ├─ Branch identified by cryptographic hash (256-bit)   │
│  ├─ Queries validated against branch token              │
│  └─ Cross-branch access: Cryptographically impossible   │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│  Layer 3: MVCC Snapshot Isolation                        │
│  ├─ Each query sees consistent snapshot                 │
│  ├─ Snapshot from specific branch only                  │
│  ├─ Isolation level: SERIALIZABLE per branch            │
│  └─ Other branches' commits invisible                   │
└─────────────────────────────────────────────────────────┘

Deployment Architecture

Kubernetes StatefulSet - One Tenant Per Container:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: heliosdb-saas-app
spec:
  serviceName: heliosdb-saas
  replicas: 50  # Scale to 50K+ tenants across cluster
  template:
    metadata:
      labels:
        app: heliosdb-saas
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - heliosdb-saas
              topologyKey: kubernetes.io/hostname

      containers:
      - name: saas-app
        image: saas-app:latest
        env:
        - name: HELIOSDB_TENANT_ID
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: HELIOSDB_DATA_DIR
          value: /data/$(HELIOSDB_TENANT_ID)

        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"

        volumeMounts:
        - name: data
          mountPath: /data

        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5

  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

Implementation Examples

Example 4: Docker Compose - Multi-Tenant Development

# Dockerfile for multi-tenant SaaS app
FROM rust:latest as builder
WORKDIR /app
COPY Cargo.* ./
COPY src ./src
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y curl ca-certificates
COPY --from=builder /app/target/release/saas-app /usr/local/bin/

# Create data directory with proper permissions
RUN mkdir -p /data && chmod 700 /data
RUN useradd -m -u 1000 app
USER app:app

EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
    CMD curl -f http://localhost:8080/health || exit 1

ENTRYPOINT ["saas-app"]
# docker-compose.yml - Multi-tenant development environment
version: '3.8'

services:
  # Load balancer - routes requests to appropriate tenant container
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - saas-app-1
      - saas-app-2

  # Tenant 1 - Customer A
  saas-app-1:
    build: .
    environment:
      TENANT_ID: customer-a
      HELIOSDB_DATA_DIR: /data/customer-a
      RUST_LOG: info
    volumes:
      - tenant-a-data:/data/customer-a
    expose:
      - 8080

  # Tenant 2 - Customer B
  saas-app-2:
    build: .
    environment:
      TENANT_ID: customer-b
      HELIOSDB_DATA_DIR: /data/customer-b
      RUST_LOG: info
    volumes:
      - tenant-b-data:/data/customer-b
    expose:
      - 8080

volumes:
  tenant-a-data:
  tenant-b-data:
# nginx.conf - Route by subdomain to tenant
upstream tenant_a {
    server saas-app-1:8080;
}

upstream tenant_b {
    server saas-app-2:8080;
}

server {
    listen 80;

    # Route customer-a.localhost to container 1
    server_name customer-a.*;
    location / {
        proxy_pass http://tenant_a;
        proxy_set_header Host $host;
    }
}

server {
    listen 80;

    # Route customer-b.localhost to container 2
    server_name customer-b.*;
    location / {
        proxy_pass http://tenant_b;
        proxy_set_header Host $host;
    }
}

Example 5: Kubernetes Multi-Tenant Scaling

# helm/values.yaml - Multi-tenant scaling configuration
replicaCount: 50

image:
  repository: saas-app
  tag: "1.0.0"

# Resource limits per tenant container
resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 256Mi

# Tenant scheduling
tenantScheduling:
  mode: "pod-per-tenant"  # or "multi-tenant-per-pod" (30:1)
  tenants_per_pod: 1

# Persistent storage per tenant
persistence:
  enabled: true
  storageClass: "fast-ssd"
  size: 10Gi  # Per tenant

# Auto-scaling based on tenant count
autoscaling:
  enabled: true
  minReplicas: 10
  maxReplicas: 100
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80
  # Add new container when reaching 30 tenants
  tenantScalingPolicy:
    replicas_per_tenant: "1/30"  # 1 replica per 30 tenants

# Backup strategy - all tenants in one pod
backup:
  enabled: true
  schedule: "0 2 * * *"  # Daily at 2 AM
  retention: 30  # days
  destination: "s3://backups/saas-tenants"
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: saas-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: StatefulSet
    name: heliosdb-saas-app
  minReplicas: 5
  maxReplicas: 200
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30

Adoption Strategy

Phase 1: Proof of Concept

Objective: Validate HeliosDB Lite for multi-tenancy use case

Activities:

  • Set up 3-tenant test environment
  • Customer A (historical data)
  • Customer B (new data)
  • Internal tenant (for testing)
  • Migrate one small customer's data
  • Validate isolation
  • Benchmark latency
  • Test backup/restore
  • Run performance tests
  • Schema migration procedures
  • Failure recovery scenarios

Phase 2: Pilot Rollout

Objective: Run parallel systems (old and new) for reliability validation

Activities:

  • Deploy HeliosDB Lite alongside PostgreSQL
  • Parallel writes to both systems
  • Compare query results (consistency check)
  • Monitor both systems simultaneously
  • Onboard 10-20 pilot customers
  • Mix of small, medium, large customers
  • Different data patterns and query types
  • Gather real production metrics
  • Establish operational procedures
  • Tenant provisioning automation
  • Backup/restore procedures
  • Incident response playbooks
  • Monitoring & alerting rules
  • Performance testing at scale
  • Load testing (simulate peak customer loads)

Phase 3: Full Production Rollout

Objective: Migrate all customers to HeliosDB Lite, retire PostgreSQL

Activities:

  • Monitor churn impact (should be zero)
  • Gather production performance data
  • Build confidence with each batch
  • Decommission old infrastructure
  • Remove PostgreSQL databases (one per week)
  • Consolidate infrastructure costs
  • Redirect savings to product development
  • Optimize for production
  • Fine-tune container resource limits
  • Optimize Kubernetes scheduling
  • Auto-scaling based on real workload patterns
  • Measure business impact
  • Cost reduction achieved vs. projected
  • Revenue impact from new isolation features (compliance sales)
  • Team productivity improvement (less ops overhead)

Conclusion

For SaaS platforms: HeliosDB Lite transforms multi-tenancy from an operational burden into a scalable, reliable, cost-effective foundation for growth.

Performance depends on workload and hardware. Published figures are measured on representative fixtures; see the benchmarks page and reproduce them on your own workload.