Multi-Tenancy
BoilStream provides full tenant isolation within a single deployment, enabling secure multi-tenant data platforms.
Isolation Model
Each tenant (user) gets isolated:
| Resource | Isolation |
|---|---|
| DuckLakes | Separate catalogs per tenant |
| Secrets | Encrypted, tenant-scoped secret storage |
| Filesystem | Chroot to tenant-specific directory |
| Attachments | Isolated DuckDB attachments |
| Sessions | Separate session management |
Architecture
DuckLake Isolation
Each user can have multiple DuckLakes, completely isolated from other users:
sql
-- User A's catalogs
FROM boilstream_ducklakes();
┌──────────────────┬─────────────────────┐
│ name │ description │
├──────────────────┼─────────────────────┤
│ analytics │ Analytics warehouse │
│ events__stream │ Event streaming │
└──────────────────┴─────────────────────┘
-- User B cannot see or access User A's catalogsDuckDB Remote Secrets Store
Tenants can store secrets remotely via the boilstream extension:
sql
-- Create persistent secret onto BoilStream server
CREATE PERSISTENT SECRET s3_minio IN boilstream (
TYPE S3,
KEY_ID 'minioadmin',
SECRET 'minioadmin',
REGION 'eu-west-1',
ENDPOINT 'localhost:9000',
USE_SSL false,
URL_STYLE 'path',
SCOPE 's3://ingestion-data/'
);
-- Secrets are automatically available after login
-- Other tenants cannot access your secretsSecrets are:
- Encrypted with AES-256-GCM
- Scoped to the authenticated tenant
- Automatically loaded on session start
- Synced across DuckDB clients
Filesystem Isolation
Each tenant is chrooted to their own directory:
yaml
# config.yaml
pgwire:
tenant_data_base_path: "/data/tenants"Results in:
/data/tenants/
├── user_abc123/ # Tenant A's files
│ ├── uploads/
│ └── exports/
├── user_def456/ # Tenant B's files
│ ├── uploads/
│ └── exports/Tenants cannot access files outside their directory.
Session Isolation
- Each tenant has independent sessions
- Session credentials are tenant-specific
- Concurrent session limits per tenant (configurable)
yaml
auth:
max_concurrent_sessions: 20 # Per user
max_session_ttl_hours: 8Role-Based Access
Superadmins can assign BoilStream roles to control tenant capabilities:
| Role | Capabilities |
|---|---|
Reader | Query DuckLakes, read secrets |
Writer | Above + create tables, ingest data |
Admin | Above + create DuckLakes, manage secrets |
Superuser | Full access |
bash
# Assign role to user
boilstream-admin roles assign data-engineers --user tenant@example.com
# Assign role to SAML group
boilstream-admin roles assign analysts --group "Data Team"S3 Bucket Isolation
Tenants can be assigned to specific S3 buckets via BoilStream roles:
bash
# Create role with bucket access
boilstream-admin roles create tenant-a-role \
--bucket tenant-a-data-bucket \
--access-level writerConfiguration
yaml
# Multi-tenant settings
pgwire:
tenant_data_base_path: "/data/tenants"
max_connections: 100 # Total across all tenants
auth:
max_concurrent_sessions: 20 # Per tenant
max_sessions_per_hour: 1000 # Rate limit per tenant
auth_server:
auto_create_default_ducklake: true # Auto-provision DuckLake for new usersBest Practices
- Use BoilStream roles - Assign roles to control tenant access levels
- Enable auto-provisioning - New users automatically get a DuckLake
- Set resource limits - Configure per-tenant session and connection limits
- Use SAML groups - Map IdP groups to BoilStream roles for SSO users
- Monitor per-tenant - Use tenant labels in Prometheus metrics
Next Steps
- Cluster Mode - Multi-tenant in clustered deployments
- Authentication - SSO and role configuration
- DuckLake Integration - Catalog management