npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nestarc/tenancy

v0.16.2

Published

Multi-tenancy module for NestJS with PostgreSQL Row Level Security (RLS) and Prisma support

Readme

@nestarc/tenancy — NestJS multi-tenancy with PostgreSQL RLS and Prisma

npm version npm downloads CI License: MIT Docs

A NestJS module that carries an authorized tenant ID through AsyncLocalStorage and sets PostgreSQL transaction-local context for Prisma model queries. PostgreSQL Row Level Security (RLS) policies then enforce which tenant's rows the database role may read or write.

Quick Start · Existing app setup · Usage reference · Compatibility · AI agent guide · Official docs

Requirements

| Dependency | 0.16.2 requirement | | --- | --- | | Node.js | ^22.23.4 \|\| ^24.22.1 | | NestJS | 10 or 11 | | Prisma | 6 or 7; the example uses Prisma 7 with @prisma/adapter-pg | | Database | PostgreSQL with RLS enabled; use a supported, patched release |

Exact CI targets, optional peer combinations, pooler limits, and migrations are documented separately. Security fixes cover the latest published minor line; see SECURITY.md.

The Node.js minimum is a 0.16.2 security change. Published 0.16.1 retains its original engine metadata, but applications using it should also upgrade their Node runtime and HTTP parser dependencies. See the runtime and parser security guidance.

Quick Start

Run the complete NestJS + Prisma example. It includes a Prisma schema, dedicated application database role, RLS SQL, two seeded tenants, authentication middleware, membership authorization, Prisma provider, and GET/POST controllers.

From a checkout of this repository, with Node.js and Docker available:

If you use nvm, run nvm install and nvm use after entering the checkout and before npm ci; .nvmrc selects Node.js 24.22.1. Check node --version in the shell that starts the application. Repository installs enforce the supported engine range through .npmrc.

git clone https://github.com/nestarc/nestjs-tenancy.git
cd nestjs-tenancy
npm ci
npm run example:quickstart:setup
npm run example:quickstart:start

In another terminal:

curl http://localhost:3000/projects \
  -H 'Authorization: Bearer demo-alice' \
  -H 'X-Tenant-Id: 11111111-1111-4111-8111-111111111111'

The response contains Alice's seeded project. Alice's token with Bob's tenant ID (22222222-2222-4222-8222-222222222222) returns 403. A missing or invalid demo credential returns 401. See the example for write requests, reset/cleanup commands, and expected responses.

A tenant header is a claim, not proof of access. The demo tokens are local fixtures. For production, replace them with your authentication provider and verify that the authenticated principal may access the resolved tenant. Register authentication with app.use(...) before Nest initialization so onTenantResolved receives the verified principal; importing an auth module first does not ensure that order. Authentication and adapter guide

Verify the example and documentation:

npm run test:docs
npm run test:docs:e2e

The first command checks documentation links, types, and HTTP contracts; the second verifies tenant isolation against the example's disposable PostgreSQL database. See the example verification notes for the exact checks and prerequisites.

Add to an existing app

Install the package and matching Prisma packages. This example uses Prisma 7; use the same supported exact version for the CLI, client, and adapter in your lockfile.

npm install @nestarc/tenancy @prisma/client@7 @prisma/adapter-pg@7 pg dotenv
npm install --save-dev prisma@7
  1. Add a required tenant column to each tenant-scoped model. Generate and review database roles, grants, indexes, and RLS policies with npx @nestarc/tenancy init. Use a non-owner application role without SUPERUSER or BYPASSRLS privileges.
  2. Register verified authentication before Nest initialization. Register TenancyModule.forRoot({ tenantExtractor: 'X-Tenant-Id', onTenantResolved: ... }), with a hook that checks the principal's tenant membership. HTTP identifiers use UUID-like validation by default; slug identifiers require a validator.
  3. Apply createPrismaTenancyExtension(tenancyService) to the Prisma client and expose that extended client through your application provider. Keep the raw client private. See Prisma configuration.
  4. Query through the extended client. For multiple operations in one interactive transaction, use tenancyTransaction() and only its callback client. Write required tenant fields explicitly there.
  5. Run check and doctor with the same setting key and runtime database role, then test tenant A/B and missing-context access.

How it works

Authenticated HTTP request + tenant claim
  → TenantMiddleware extracts and validates the tenant ID
    → AsyncLocalStorage establishes the tenant context
      → onTenantResolved authorizes it against the verified principal
        → TenancyGuard requires context for protected HTTP routes
          → Extended Prisma model query
            → transaction-local set_config() + query on the same transaction
              → PostgreSQL RLS evaluates the configured policies

AsyncLocalStorage avoids Nest's REQUEST-scoped providers. The extension adds transaction/context-setting work; see benchmark methodology and reproducible evidence for measuring it in your environment.

Usage reference

| Task | Guide | | --- | --- | | Header, subdomain, JWT, path, or fallback extraction; authentication; hooks | HTTP configuration | | Model extension options, tenant injection, transactions, shared models, administration | Prisma and transactions | | TenancyModule, TenancyService, decorators, errors | Core API reference | | Testing helpers, events, OpenTelemetry, HTTP/RPC propagation, caching | Integrations | | SQL policies, application role, schema migration, PgBouncer, CLI diagnostics | Database operations | | Deploying the security update: runtime, HTTP parser, and resource keys | Upgrade and deployment sequence | | Supported versions, exact CI lanes, deprecated APIs | Compatibility and migrations | | Integrating the package with an AI coding agent | Version-scoped agent usage guide | | Maintaining this repository and preparing a release | Documentation and release checklist |

Important boundaries

  • Database configuration remains necessary. Apply RLS to every tenant table and connect with the intended application role. RLS protects rows; it does not authorize caller-supplied tenant IDs or isolate CPU/IO, caches, search indexes, or jobs.
  • Fail-closed is enabled for model queries. Missing context throws TenancyContextRequiredError unless explicitly bypassed at the client layer. sharedModels and withoutTenant() skip extension hooks; they do not disable database RLS or grant administrative access. Details
  • Raw SQL uses an explicit transaction. $queryRaw and $executeRaw are outside the model extension. Run them on the callback client from tenancyTransaction() so the tenant setting and SQL share one transaction. The package binds its set_config() arguments; application SQL still needs proper parameterization.
  • Interactive transactions use the helper. The default extension's batch transaction does not automatically work inside a Prisma interactive transaction. The helper's raw transaction client does not auto-inject tenant fields. Transaction contract
  • Non-HTTP transports need their own trust boundary. Kafka, Bull, and gRPC restoration need an explicit validator and producer-to-tenant authorization. WebSocket inbound enforcement is not provided. RPC guide
  • Adapter and pooler support has conditions. Public structural request types do not prove every adapter hook works; review HTTP prerequisites. The pinned self-hosted PgBouncer transaction-mode matrix has a specific contract; managed poolers and Data Proxy require separate validation.

License

MIT