TenancyJS
Integrations

NestJS

Scope every NestJS request with a module and interceptor - Express or Fastify, any ORM.

tenancyjs-integration-nest brings tenant scoping to NestJS 11. Register the tenancy module and an interceptor opens a tenant scope for the lifetime of each request; your controllers and providers run inside it. It works on both the Express and Fastify platforms.

Works with any ORM. Prisma · Knex · TypeORM · Sequelize · Drizzle · Mongoose.

NestJS is fully supported, but tenancy init doesn't scaffold it yet - this is the manual setup (a few lines). See Installation.

Install

npm install tenancyjs-core tenancyjs-integration-nest tenancyjs-adapter-prisma @prisma/client

Wire it up

Provide your application-owned manager and resolution service. TenancyModule registers its global guard and interceptor; do not register a second copy.

app.module.ts
import { Module } from "@nestjs/common";
import { TenantResolutionChain, HeaderTenantResolver } from "tenancyjs-identifiers";
import { TenancyModule } from "tenancyjs-integration-nest";
import { manager, tenantStore } from "./tenancy";

const resolver = new TenantResolutionChain({
  resolvers: [new HeaderTenantResolver()],
  store: tenantStore,
});

@Module({
  imports: [TenancyModule.forRoot({ manager, resolver })],
})
export class AppModule {}

Mark tenant routes explicitly and use your adapter's protected API inside the handler:

posts.controller.ts
import { Controller, Get } from "@nestjs/common";
import { TenantRoute } from "tenancyjs-integration-nest";
import { typeormTenancy } from "./tenancy";
import { Post } from "./entities/post";

@Controller("posts")
export class PostsController {
  @Get()
  @TenantRoute()
  list() {
    return typeormTenancy.run((client) =>
      client.repository(Post).findBy({ status: "open" }),
    );
  }
}

How it behaves

  • Each request resolves its tenant and runs inside the scope; ORM queries through the adapter are scoped.
  • A resolution failure fails closed with the correct HTTP status before your controller runs.
  • Authorization guards may inject NestTenantResolutionStore to read the resolved tenant. The canonical TenancyManager context begins later in the interceptor and covers the handler Observable.
  • Unmarked routes are neither tenant nor central routes.

The optional executor setting is for transaction executors whose scoped resource is already available to application operations (for example an ALS-backed integration). Callback-only facades such as TypeORM and Sequelize should normally be called directly in the handler as shown above; passing them as an executor does not inject their callback client into Nest providers.

Use a different ORM

For the exact lifecycle and security boundary, see the package README.

On this page