Through TenantsDB, each tenant gets their own MongoDB database with the same collections and indexes, deployed from a blueprint. The proxy handles routing, TLS, query logging, and settings enforcement. Your app connects with any standard MongoDB driver. No SDK needed.
The proxy supports the full MongoDB wire protocol including cursors, aggregation pipelines, and GridFS. TLS is handled at the edge via HAProxy, so ?tls=true works for every driver and language. All connections use authMechanism=PLAIN over TLS, so credentials are never sent in the clear.
mongosh "mongodb://tdb_2abf90d3:[email protected]:27017/controlplane_workspace?authMechanism=PLAIN&directConnection=true&tls=true"
Control mode workspaces accept all operations immediately. No blueprint versioning, no deployment step. Use this for your application's own collections that are not per-tenant.
mongosh "mongodb://tdb_2abf90d3:[email protected]:27017/myapp_workspace?authMechanism=PLAIN&directConnection=true&tls=true"
Every createCollection, createIndex, or other structural operation you run here is captured as a blueprint version. Deploy it to all tenants with tdb deployments create --blueprint myapp --all.
mongosh "mongodb://tdb_2abf90d3:[email protected]:27017/myapp__acme?authMechanism=PLAIN&directConnection=true&tls=true"
mongosh "mongodb://tdb_2abf90d3:[email protected]:27017/myapp__globex?authMechanism=PLAIN&directConnection=true&tls=true"
createCollection, createIndex) are blocked on tenant connections.db.createCollection("accounts") db.accounts.insertMany([ { name: "Alice", email: "[email protected]", balance: 1000 }, { name: "Bob", email: "[email protected]", balance: 2000 } ]) db.accounts.createIndex({ email: 1 }, { unique: true })
createCollection, createIndex, etc.) are tracked as blueprint changes. Data operations (insertMany, updateMany, deleteMany) run in the workspace only and are not deployed to tenants.
You can also import an existing schema from another database or use a template. See tdb workspaces schema --help for all options.
const mongoose = require('mongoose'); const url = 'mongodb://tdb_2abf90d3:[email protected]:27017/myapp__acme?authMechanism=PLAIN&directConnection=true&tls=true'; await mongoose.connect(url); // Define schema const Account = mongoose.model('Account', new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, balance: { type: Number, default: 0 }, created_at: { type: Date, default: Date.now } })); // Query const accounts = await Account.find(); await Account.create({ name: 'Alice', email: '[email protected]', balance: 1000 });
npm install mongoose
?tls=true.from pymongo import MongoClient url = "mongodb://tdb_2abf90d3:[email protected]:27017/myapp__acme?authMechanism=PLAIN&directConnection=true&tls=true" client = MongoClient(url) db = client.get_default_database() # Query accounts = list(db.accounts.find()) db.accounts.insert_one({ "name": "Alice", "email": "[email protected]", "balance": 1000 })
pip install pymongo
?tls=true and authMechanism=PLAIN natively.package main import ( "context" "fmt" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { ctx := context.Background() url := "mongodb://tdb_2abf90d3:[email protected]:27017/myapp__acme?authMechanism=PLAIN&directConnection=true&tls=true" client, _ := mongo.Connect(ctx, options.Client().ApplyURI(url)) defer client.Disconnect(ctx) col := client.Database("myapp__acme").Collection("accounts") // Query cursor, _ := col.Find(ctx, bson.M{}) var results []bson.M cursor.All(ctx, &results) fmt.Printf("Found %d accounts\n", len(results)) // Insert col.InsertOne(ctx, bson.M{ "name": "Alice", "email": "[email protected]", "balance": 1000, }) }
go get go.mongodb.org/mongo-driver/mongo
The proxy handles the full MongoDB wire protocol. BSON messages are forwarded natively without parsing individual field values. Cursors, aggregation pipelines, and all standard MongoDB operations work through the proxy.
All connections use authMechanism=PLAIN and directConnection=true. PLAIN auth is transmitted over TLS (terminated at the edge by HAProxy), so credentials are never sent in the clear. The directConnection=true parameter is required because the proxy is not a MongoDB replica set.
GridFS is fully supported. Files larger than 16MB are split into 255KB chunks that flow through the proxy as normal find/insert operations. The max_rows_per_query setting automatically skips GridFS collections (.chunks and .files) so file transfers are never truncated.
The proxy enforces max_rows_per_query, query_timeout_ms, and max_connections at the proxy level. These are configured per workspace and apply to all tenants using that blueprint.
Standard MongoDB limits apply: 16MB per BSON document, 48MB per wire protocol message. Cursor pagination works in all modes. Queries returning more than 101 documents page through getMore correctly, including in blueprint mode with routing field extraction.