MultiBridge is a powerful multi-tenant database connection framework that supports PostgreSQL, MySQL, MongoDB, and Cassandra. It provides a unified interface for managing tenant-specific database connections with automatic routing, connection pooling, caching, and ORM integration.
- π’ Multi-tenant database connection management with automatic tenant routing
- ποΈ Multi-database support: PostgreSQL, MySQL, MongoDB, and Cassandra
- π Connection pooling with configurable pool sizes
- πΎ LRU connection caching with TTL for optimal performance
- π Tenant context management using
AsyncLocalStorage - β‘ Eager connection establishment for better performance
- π SQL injection prevention with automatic sanitization
- β±οΈ Query timeouts with configurable timeouts per database type
- π Automatic retry logic with exponential backoff
- π¦ Rate limiting to prevent connection exhaustion
- π Sequelize adapter for PostgreSQL and MySQL
- π TypeORM adapter for PostgreSQL, MySQL, and MongoDB
- π Mongoose adapter for MongoDB
- π Cassandra ORM-like adapter with CRUD helpers
- π TypeScript support with full type definitions
- π― Custom error classes for better error handling
- π Connection statistics API for monitoring
- π Comprehensive documentation with examples
- π‘οΈ Input validation for tenant identifiers
- π Structured logging with Winston
npm install multibridgeInstall ORM packages as needed (they are peer dependencies):
# For Sequelize
npm install sequelize pg mysql2
# For TypeORM
npm install typeorm pg mysql2 mongodb
# For Mongoose
npm install mongoose
# Cassandra driver is included as a dependencyCreate a .env file in your project root:
# Central Database Configuration (PostgreSQL)
CENTRAL_DB_HOST=localhost
CENTRAL_DB_PORT=5432
CENTRAL_DB_USER=admin
CENTRAL_DB_PASSWORD=password
CENTRAL_DB_NAME=central_db
CENTRAL_DB_TABLE=connections_config
# Logging
LOG_LEVEL=info
# Optional: Performance Tuning
CONNECTION_CACHE_MAX_SIZE=100
CONNECTION_CACHE_TTL_MS=3600000
POSTGRES_POOL_MAX=20
POSTGRES_POOL_MIN=5
MYSQL_POOL_MAX=10
QUERY_TIMEOUT_MS=30000import { runWithTenant, executeQuery, ConnectVo } from "multibridge";
const tenant: ConnectVo = {
appid: "myApp",
orgid: "org123",
appdbname: "tenant_db",
};
// Execute queries in tenant context
await runWithTenant(tenant, async () => {
// PostgreSQL/MySQL
const users = await executeQuery("SELECT * FROM users WHERE id = ?", [userId]);
// MongoDB
const user = await executeQuery({
collection: "users",
method: "findOne",
args: [{ email: "user@example.com" }],
});
// Cassandra
const data = await executeQuery(
"SELECT * FROM users WHERE user_id = ?",
[userId]
);
});import { runWithTenant, getSequelizeInstance } from "multibridge";
import { Sequelize } from "sequelize";
await runWithTenant(tenant, async () => {
const sequelize = await getSequelizeInstance();
const User = sequelize.define("User", {
username: Sequelize.STRING,
email: Sequelize.STRING,
});
const users = await User.findAll();
});import { runWithTenant, getTypeORMDataSource } from "multibridge";
import { User } from "./entities/User";
await runWithTenant(tenant, async () => {
const dataSource = await getTypeORMDataSource({
entities: [User],
});
const userRepo = dataSource.getRepository(User);
const users = await userRepo.find();
});import { runWithTenant, getMongooseConnection } from "multibridge";
import { Schema } from "mongoose";
await runWithTenant(tenant, async () => {
const connection = await getMongooseConnection();
const User = connection.model("User", new Schema({
username: String,
email: String,
}));
const users = await User.find();
});import { runWithTenant, getCassandraClient, insert, select } from "multibridge";
await runWithTenant(tenant, async () => {
const client = await getCassandraClient();
// Insert
await insert(client, "users", {
user_id: "123",
username: "john",
email: "john@example.com",
});
// Select
const users = await select(client, "users", ["user_id", "username"], {
user_id: "123",
});
});For comprehensive examples and detailed usage patterns, see:
- EXAMPLE.md - Complete usage guide with controllers, services, ORM integration, and best practices
- CHANGELOG.md - Version history and migration guides
Execute code within a tenant context.
await runWithTenant(tenant, async () => {
// Your code here
}, { lazyConnection: false }); // Default: false (eager connection)Execute a query in the current tenant context.
// SQL (PostgreSQL/MySQL)
await executeQuery("SELECT * FROM users WHERE id = ?", [userId]);
// MongoDB
await executeQuery({
collection: "users",
method: "findOne",
args: [{ email: "user@example.com" }],
});
// Cassandra
await executeQuery("SELECT * FROM users WHERE user_id = ?", [userId]);Get the current tenant's database connection.
const { connection, dbType, config } = await getConnection();Get connection statistics for monitoring.
const stats = getConnectionStats();
console.log(stats.activeConnections);
console.log(stats.cachedConnections);getSequelizeInstance(options?)- Get Sequelize instancecloseSequelizeInstance(tenant?)- Close instance for tenantcloseAllSequelizeInstances()- Close all instances
getTypeORMDataSource(options?)- Get TypeORM DataSourcecloseTypeORMDataSource(tenant?)- Close DataSource for tenantcloseAllTypeORMDataSources()- Close all DataSources
getMongooseConnection(options?)- Get Mongoose connectioncloseMongooseConnection(tenant?)- Close connection for tenantcloseAllMongooseConnections()- Close all connections
getCassandraClient()- Get Cassandra clientexecuteCQL(query, params?)- Execute CQL querycreateTable(client, model)- Create table from modelinsert(client, table, data)- Insert dataselect(client, table, columns, where?)- Select dataupdate(client, table, data, where)- Update dataremove(client, table, where)- Delete datacloseCassandraClient(tenant?)- Close client for tenantcloseAllCassandraClients()- Close all clients
MultiBridge provides custom error classes:
import {
MultiBridgeError,
TenantContextError,
ConnectionError,
ConfigurationError,
ValidationError,
QueryError,
TimeoutError,
} from "multibridge";
try {
await runWithTenant(tenant, async () => {
await executeQuery("SELECT * FROM users");
});
} catch (error) {
if (error instanceof TenantContextError) {
// Handle tenant context errors
} else if (error instanceof ConnectionError) {
// Handle connection errors
} else if (error instanceof QueryError) {
// Handle query errors
} else if (error instanceof TimeoutError) {
// Handle timeout errors
}
}| Variable | Description | Default |
|---|---|---|
CENTRAL_DB_HOST |
Central database host | localhost |
CENTRAL_DB_PORT |
Central database port | 5432 |
CENTRAL_DB_USER |
Central database user | - |
CENTRAL_DB_PASSWORD |
Central database password | - |
CENTRAL_DB_NAME |
Central database name | - |
CENTRAL_DB_TABLE |
Configuration table name | connections_config |
LOG_LEVEL |
Logging level | info |
CONNECTION_CACHE_MAX_SIZE |
Max cached connections | 100 |
CONNECTION_CACHE_TTL_MS |
Connection cache TTL | 3600000 (1 hour) |
POSTGRES_POOL_MAX |
PostgreSQL max pool size | 20 |
POSTGRES_POOL_MIN |
PostgreSQL min pool size | 5 |
MYSQL_POOL_MAX |
MySQL max pool size | 10 |
QUERY_TIMEOUT_MS |
Default query timeout | 30000 (30s) |
CONNECTION_RETRY_ATTEMPTS |
Retry attempts | 3 |
CONNECTION_RETRY_DELAY_MS |
Retry delay | 1000 (1s) |
RATE_LIMIT_MAX_REQUESTS |
Rate limit max requests | 10 |
RATE_LIMIT_WINDOW_MS |
Rate limit window | 1000 (1s) |
See EXAMPLE.md for complete configuration options.
src/
βββ config/ # Configuration management
β βββ dbConfig.ts # Central database configuration
β βββ envConfig.ts # Environment variable configuration
βββ connections/ # Database connection management
β βββ connectionManager.ts # Core connection manager
β βββ postgres.ts # PostgreSQL connection
β βββ mysql.ts # MySQL connection
β βββ mongodb.ts # MongoDB connection
β βββ cassandra.ts # Cassandra connection
βββ context/ # Tenant context management
β βββ tenantContext.ts
βββ helpers/ # Database-specific helpers
β βββ mongodbHelper.ts
β βββ cassandraHelper.ts
βββ orm/ # ORM adapters
β βββ sequelize.ts
β βββ typeorm.ts
β βββ mongoose.ts
β βββ cassandra.ts
βββ utils/ # Utility functions
β βββ executeQuery.ts
β βββ errors.ts
β βββ loggers.ts
β βββ lruCache.ts
β βββ rateLimiter.ts
βββ types/ # TypeScript type definitions
βββ dbTypes.ts
- Tenant Context:
runWithTenantestablishes a tenant context usingAsyncLocalStorage - Configuration Lookup: MultiBridge queries the central database to get tenant-specific connection details
- Connection Caching: Connections are cached using LRU cache with TTL
- Query Execution:
executeQueryautomatically routes queries to the correct tenant database - ORM Integration: ORM adapters use MultiBridge's connection management
- β SQL Injection Prevention: Automatic schema name sanitization
- β CQL Injection Prevention: Identifier sanitization for Cassandra
- β Input Validation: Tenant identifier validation
- β Password Sanitization: Passwords are sanitized in logs
- β Type Safety: Full TypeScript support for type safety
- π Connection Caching: LRU cache with configurable size and TTL
- π Configuration Caching: Central DB config caching
- π Connection Pooling: Configurable pool sizes
- π Lazy Validation: Connection validation only when needed
- π Race Condition Prevention: Promise-based locking
- π Rate Limiting: Prevents connection exhaustion
my-app/
βββ src/
β βββ controllers/
β β βββ userController.ts
β βββ services/
β β βββ userService.ts
β βββ models/
β β βββ sequelize/
β β β βββ User.ts
β β βββ typeorm/
β β βββ User.entity.ts
β βββ routes/
β β βββ userRoutes.ts
β βββ server.ts
βββ .env
βββ package.json
See EXAMPLE.md for complete examples.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with TypeScript for type safety
- Uses Winston for structured logging
- Supports popular ORMs: Sequelize, TypeORM, Mongoose
- π Documentation
- π Issue Tracker
- π¬ GitHub Discussions