MANGGA SANTAI WAE HATUR NUHUN GASKEUN MANGGA SANTAI WAE HATUR NUHUN GASKEUN

Article

Introducing FlexiDB - A Multi-Database Solution for Prisma Developers

FlexiDB is a lightweight, type-safe abstraction layer for managing multiple independent databases in one Node.js app, with Prisma integration, dynamic runtime registration, and built-in health checks.

Introducing FlexiDB - A Multi-Database Solution for Prisma Developers
M
Muhammad Surya

Overview

Managing multiple databases in a single Node.js application gets messy fast, especially with Prisma, which traditionally supports only one database per schema. That limitation usually pushes developers toward merging schemas, hand-rolling client lifecycle management, or other workarounds nobody enjoys.

I built FlexiDB to get rid of that pain: a lightweight, type-safe abstraction layer on top of Prisma v6 and v7+ for managing multiple databases. With FlexiDB, you can register, access, and manage several independent databases without merging schemas, restarting your server, or writing the boilerplate you’d otherwise need.

Why FlexiDB

1. No schema merging

Each database gets its own .prisma file, so you never have to cram everything into a single schema.prisma. Your project stays organized as it grows.

2. Dynamic registration

Need to add or remove a database while the app is running? FlexiDB lets you register and unregister databases at runtime, which matters a lot if you’re building multi-tenant architecture.

3. Built-in health checks

db.health() and db.stats() give you the connection status of every registered database so you can catch problems before they take down a request.

4. Connection retry

If the network drops, FlexiDB reconnects automatically with exponential backoff instead of leaving you with a dead client.

5. Event hooks

Lifecycle hooks like onConnect, onDisconnect, onError, and onRetry give you a place to react to what’s happening to each connection.

6. CLI tooling

The flexidb CLI handles the repetitive parts: generating Prisma clients, running migrations, and scaffolding new projects across multiple schemas.

Key features

Multi-database support

Register as many databases as you need, each with its own .prisma file and Prisma client.

const db = createFlexiDB({
  user:      new UserPrismaClient({ adapter: userAdapter }),
  analytics: new AnalyticsPrismaClient({ adapter: analyticsAdapter }),
});

Dynamic runtime registration

Add or remove databases dynamically at runtime using db.register() and db.unregister().

db.register('tenant_acme', new TenantClient({ adapter: acmeAdapter }));
await db.unregister('tenant_acme');

Health checks and statistics

Monitor database connectivity and performance with db.health() and db.stats().

const status = await db.health();
// { user: true, analytics: false }

const stats = db.stats();
// { user: { connected: true, lastError: null }, analytics: { connected: false, lastError: Error } }

Auto-generated code

The npx flexidb codegen command reads your schemas and generates a ready-to-use db.ts file with all imports and configurations.

npx flexidb codegen

CLI commands

Run Prisma commands across all schemas at once:

# Generate Prisma clients for all schemas
npx flexidb generate

# Apply migrations to all databases
npx flexidb migrate deploy

# Open Prisma Studio for a specific schema
npx flexidb studio --schema user

Getting started with FlexiDB

Step 1: Install dependencies

npm install flexidb prisma @prisma/client
# or
yarn add flexidb prisma @prisma/client

Step 2: Scaffold your project (optional)

If you’re starting from scratch, run:

npx flexidb init

This creates a prisma/schemas/ directory, an example schema, and a .env.example file.

Step 3: Define your schemas

Create separate .prisma files for each database under prisma/schemas/.

// prisma/schemas/user.prisma
generator client {
  provider = "prisma-client"
  output   = "../../src/generated/user"
}

datasource db {
  provider = "mysql"
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  createdAt DateTime @default(now())
}

Step 4: Generate Prisma clients

npx flexidb generate

This generates Prisma clients for all schemas in prisma/schemas/.

Step 5: Auto-generate your db.ts

npx flexidb codegen

This creates a src/db.ts file with all imports and configurations wired up.

import { createFlexiDB } from 'flexidb';
import { PrismaClient as UserPrismaClient } from './generated/user/client';
import { PrismaClient as AnalyticsPrismaClient } from './generated/analytics/client';

export const db = createFlexiDB({
  user:      new UserPrismaClient({ adapter: userAdapter }),
  analytics: new AnalyticsPrismaClient({ adapter: analyticsAdapter }),
});

Step 6: Use it anywhere

import { db } from './db';

// Query user database
const users = await db.get('user').user.findMany();

// Query analytics database
const events = await db.get('analytics').event.findMany();

Connecting to databases

FlexiDB supports both Prisma v6 (URL-based) and Prisma v7+ (adapter-based) connections.

Prisma v7+ (adapter-based)

Install the adapter for your database:

npm install @prisma/adapter-mysql mysql2

Configure the adapter:

import { PrismaMysql } from '@prisma/adapter-mysql';
import { createPool } from 'mysql2';

const userAdapter = new PrismaMysql(
  createPool({ uri: process.env.DATABASE_URL_USER })
);

export const db = createFlexiDB({
  user: new UserPrismaClient({ adapter: userAdapter }),
});

Prisma v6 (URL-based)

Pass the connection URL directly:

export const db = createFlexiDB({
  user: new UserPrismaClient({
    datasourceUrl: process.env.DATABASE_URL_USER,
  }),
});

Multi-tenancy example

This is where FlexiDB earns its keep. You can register tenant databases dynamically, as they’re created:

import { createFlexiDB } from 'flexidb';
import { PrismaClient as TenantClient } from './generated/tenant/client';
import { PrismaMysql } from '@prisma/adapter-mysql';
import { createPool } from 'mysql2';

export const db = createFlexiDB({
  core: new CorePrismaClient({ adapter: coreAdapter }),
});

export async function onTenantCreated(tenantId: string, dbUrl: string) {
  const adapter = new PrismaMysql(createPool({ uri: dbUrl }));
  db.register(tenantId, new TenantClient({ adapter }));
}

export async function onTenantDeleted(tenantId: string) {
  await db.unregister(tenantId);
}

Conclusion

FlexiDB solves a specific, annoying problem: managing multiple databases in one Node.js app without fighting Prisma’s single-schema assumption. Between the Prisma integration, dynamic runtime registration, and built-in health checks, it holds up well in multi-tenant setups and microservices where you’re juggling more than one connection.

If you’re building a SaaS platform, stitching together legacy systems, or working across data lakes, FlexiDB keeps the multi-database plumbing out of your way while keeping full TypeScript support and type safety.

Source and docs are on GitHub.


License: ISC Built in Indonesia. Open source. No hidden magic, just TypeScript.