Express
Add multi-tenancy to Express with one middleware - works with any ORM.
tenancyjs-integration-express resolves the tenant for each request and runs that request inside the
tenant's scope. Everything downstream - routes, services, ORM queries - is automatically scoped.
Works with any ORM. Prisma · Knex · TypeORM · Sequelize · Drizzle · Mongoose. This guide uses Prisma; swap the adapter for yours (the middleware is identical).
Install
The framework integration plus your ORM's adapter (Prisma shown):
npm install tenancyjs-core tenancyjs-integration-express tenancyjs-adapter-prisma @prisma/clientWire it up
Manager + adapter
import { TenancyManager } from "tenancyjs-core";
import { createPrismaAdapter } from "tenancyjs-adapter-prisma";
import { PrismaClient } from "@prisma/client";
export interface Tenant {
readonly id: string;
}
export const manager = new TenancyManager<Tenant>();
const adapter = createPrismaAdapter({ manager, tenantModels: { Order: {} } });
export const db = new PrismaClient().$extends(adapter.extension);The middleware
Register it early, before your routes. Give it your manager and a resolver that turns a request
into a tenant.
import express from "express";
import { createExpressTenancyMiddleware } from "tenancyjs-integration-express";
import { manager, db } from "./tenancy";
const app = express();
app.use(
createExpressTenancyMiddleware({
manager,
resolver: (req) => ({ id: req.subdomains.at(-1) ?? "" }),
}),
);
app.get("/orders", async (_req, res) => {
res.json(await db.order.findMany()); // already scoped to the tenant
});How it behaves
- On success: the tenant scope is open for the whole request; adapters are scoped, and the scope is torn down when the response finishes.
- On a resolution failure: a missing/invalid identifier or an unknown/suspended tenant makes the middleware respond 400/404 - your handler never runs.
Use a different ORM
Keep the middleware; swap the adapter half. Each adapter page has a complete Express example:
Resolving the tenant
The resolver is yours - subdomain, header, path, JWT claim. For lookups against your store and consistent 400/404 semantics, see Resolving tenants.