How Connections Work
Your application never connects to raw database servers. Every connection goes through the TenantsDB proxy, which reads the database name from your connection string and routes to the right backend.
How routing works
Your Application
Same host · Same credentials · Different database name
↓
TenantsDB Proxy
TLS encrypted · Routes by database name
↓
controlplane_workspace
→
Your backend — users, billing, config
myapp_workspace
→
Schema design — DDL tracked as blueprint
myapp__acme
→
Customer A — isolated data, CRUD only
myapp__globex
→
Customer B — isolated data, CRUD only
One credential, one proxy. The database name controls everything.
Your app connects to
pg.tenantsdb.com, mysql.tenantsdb.com, mongo.tenantsdb.com, or redis.tenantsdb.com. Same pattern for every database type. Three Connection Types
Every connection to TenantsDB falls into one of three categories. Same proxy, same credentials; the database name determines which type.
Control
Your App's Backend
Users, billing, config; everything that isn't per-tenant. Full DDL and DML access. No blueprints, no versioning.
controlplane_workspace
Workspace
Schema Design
Where you build and iterate on your schema. DDL changes are tracked as versioned blueprints and deployed to tenants.
myapp_workspace
Tenant
Customer Database
Isolated production database for one customer. Schema deployed from blueprint. CRUD only — DDL is blocked.
myapp__acme
| Type | DDL | DML | Blueprint | Who connects |
|---|---|---|---|---|
| Control | ✓ Full access | ✓ | None | Your application |
| Workspace | ✓ Tracked | ✓ | Versioned | You, during development |
| Tenant | ✗ Blocked | ✓ | Deployed | Your application, per customer |
Your application typically holds two connection pools: one to the control database (shared across all requests) and one per tenant (resolved from authentication). See Quick Start for the full wiring pattern.
Query Paths
There are two ways to run a query against a tenant. Both land on the same database. Both enforce the same role. Pick the one that matches your client.
Wire-protocol proxy
Native database clients
psql, mysqlsh, mongosh, redis-cli, and any ORM (pg, mysql2, mongoose, ioredis, GORM, SQLAlchemy, Prisma).
pg.tenantsdb.com:5432
Authenticates with
proxy_password. Native SQL/Mongo/Redis only.HTTP API
tdb CLI, curl, MCP clients
tdb query, direct curl against the API, OAuth/MCP integrations like Claude.
api.tenantsdb.com
Authenticates with
api_key. Accepts OQL and native queries.| Wire-protocol proxy | HTTP API | |
|---|---|---|
| Host | pg.tenantsdb.com / mysql. / mongo. / redis. |
api.tenantsdb.com |
| Authenticates with | proxy_password (short) |
api_key (long, tdb_sk_ prefix) in Authorization: Bearer |
| Query languages | Native SQL / Mongo / Redis only | Native or OQL |
| Per-tenant query | Connect with myapp__acme as the database name |
POST /tenants/{id}/query |
| Cross-tenant fan-out | Not supported (one DB per connection) | POST /admin/query with all_tenants: true — role=admin only |
| Role enforcement | Database role (admin/write/read) at the SQL/Mongo/Redis layer | Same database role at the SQL/Mongo/Redis layer — defense in depth |
| DDL on tenants | Blocked — deploy via blueprints | Blocked — deploy via blueprints |
| Best for | Application backends with ORMs, dashboards using BI tools, anything that opens a long-lived database connection | CLI workflows, AI/MCP clients, scripts, any caller that does not want to manage a wire-protocol connection pool |
A key's
role applies to both paths. A read-role key attempting an INSERT is rejected the same way whether the request comes through the proxy or the HTTP API. The role is enforced natively by the database itself, not by the proxy. Connection Format
Database names follow a consistent pattern. The proxy uses the name to identify the workspace or tenant.
| Type | Pattern | Example |
|---|---|---|
| Control workspace | {name}_workspace |
controlplane_workspace |
| Tenant workspace | {blueprint}_workspace |
myapp_workspace |
| Tenant database | {blueprint}__{tenant} |
myapp__acme |
Double underscore
__ is a reserved separator. Workspace and tenant names cannot contain __. Endpoints
One host per database type. All connections require TLS.
| Database | Host | Port | TLS |
|---|---|---|---|
| PostgreSQL | pg.tenantsdb.com | 5432 | ?sslmode=require |
| MySQL | mysql.tenantsdb.com | 3306 | TLS required |
| MongoDB | mongo.tenantsdb.com | 27017 | &tls=true |
| Redis | redis.tenantsdb.com | 6379 | rediss:// scheme |
PostgreSQL
postgresql://{project_id}:{password}@pg.tenantsdb.com:5432/{database}?sslmode=require
MySQL
mysql://{project_id}:{password}@mysql.tenantsdb.com:3306/{database}
MongoDB
mongodb://{project_id}:{password}@mongo.tenantsdb.com:27017/{database}?authMechanism=PLAIN&directConnection=true&tls=true
Redis
rediss://{tenant_id}:{api_key}@redis.tenantsdb.com:6379/0
MySQL TLS is configured per driver, not via URL parameter. See the MySQL page for per-language examples.
Choose Your Database
Each database has its own connection guide with shell commands, ORM examples, and proxy behavior. Pick yours.