Skip to content
Skillpedia
APIs & servers (backend)48k · #4041

saas-multi-tenant

Helps your agent build systems where multiple customers use the same software securely. Ensures one customer's data isn't seen by another.

What it does

This tool helps build applications where multiple customers (or 'tenants') securely share the same database. It ensures each customer only sees their own data.

When to use it

  • ✓When building a SaaS application for multiple customers.
  • ✓When you need to isolate each customer's data.
  • ✓When implementing security so customers don't see each other's data.

Example of what to ask your AI

“How can I ensure one customer's data isn't seen by another in my SaaS app?”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/saas-multi-tenant/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/saas-multi-tenant/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

It sets up the database to add a customer ID column to each table and uses security rules to filter data automatically. It also creates a 'middleware' that defines which customer is accessing data on each request.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add sickn33/agentic-awesome-skills --skill saas-multi-tenant

Or download just the file:

curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/saas-multi-tenant/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

SaaS Multi-Tenant Architecture

When to Use This Skill

  • The user is building a SaaS application where multiple customers share the same database
  • The user asks about tenant isolation, row-level security, or data leakage prevention
  • The user needs to scope every database query to a specific tenant without manual WHERE clauses
  • The user asks about shared-schema vs schema-per-tenant vs database-per-tenant tradeoffs
  • The user is implementing admin endpoints that must access data across tenants
  • The user needs to add tenant_id columns to an existing single-tenant application
  • The user asks about PostgreSQL RLS policies for tenant isolation
  • The user is building tenant-aware middleware in Express, Fastify, or Next.js API routes

Do NOT use this skill when:

  • The user is building a single-user application with no shared infrastructure
  • The user asks about authentication only without tenant scoping (use an auth skill instead)
  • The user needs general database schema design without multi-tenancy requirements

Core Workflow

  1. Determine the tenancy model. Ask the user about their scale expectations and isolation requirements. For most SaaS apps under 1000 tenants, shared-schema with a tenant_id column on every table is the correct default. Schema-per-tenant adds operational overhead (migrations run N times). Database-per-tenant is only justified when tenants have regulatory data residency requirements.

  2. Add tenant_id to every tenant-scoped table. The column must be NOT NULL, type UUID or TEXT, and included in every composite index. Never allow a tenant-scoped table to exist without this column — a missing tenant_id is a data leak waiting to happen.

  3. Set up PostgreSQL Row-Level Security (RLS). Create a policy on each tenant-scoped table that filters rows by current_setting('app.current_tenant_id'). This acts as a database-level safety net — even if application code forgets a WHERE clause, RLS blocks cross-tenant reads.

  4. Build tenant-aware middleware. At the start of every request, extract the tenant_id from the authenticated session or JWT claims. Set it on the database connection using SET LOCAL app.current_tenant_id = '...' inside a transaction. Every subsequent query in that request inherits the tenant scope automatically.

  5. Scope all ORM queries by tenant. If using Prisma, apply a global middleware that injects where: { tenantId } into every findMany, findFirst, update, and delete call. If using Drizzle, create a base query builder that includes the tenant filter. Never rely on developers remembering to add the filter manually.

  6. Handle tenant-aware migrations. Every new table migration must include tenant_id as a column. Write a linting rule or CI check that rejects any migration creating a table without tenant_id unless the table is explicitly marked as global (e.g., plans, feature_flags).

  7. Build cross-tenant admin routes separately. Admin endpoints that aggregate data across tenants must bypass RLS explicitly using SET LOCAL role = 'admin_bypass' or a dedicated database role. These routes must be protected by a separate admin authentication flow — never reuse tenant user sessions for admin access.

  8. Implement tenant provisioning. When a new customer signs up, create their tenant record, seed default data (roles, settings, onboarding state), and assign the founding user. Wrap this in a database transaction so partial provisioning never leaves orphan records.

Examples

Example 1: PostgreSQL RLS Policy for Tenant Isolation

-- Enable RLS on the table
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects FORCE ROW LEVEL SECURITY;

-- Policy: users can only see rows where tenant_id matches the session variable
CREATE POLICY tenant_isolation ON projects
  USING (tenant_id = current_setting('app.current_tenant_id')::uuid);

-- Policy for INSERT: new rows must match the current tenant
CREATE POLICY tenant_insert ON projects
  FOR INSERT
  WITH CHECK (tenant_id = current_setting('app.current_tenant_id')::uuid);

Example 2: Express Middleware That Sets Tenant Context per Request

import { Pool } from "pg";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

async function tenantMiddleware(req, res, next) {
  const tenantId = req.auth?.tenantId; // extracted from JWT during auth
  if (!tenantId) return res.status(403).json({ error: "No tenant context" });


…
FAQ

What is a 'tenant'?

A 'tenant' is an individual customer of your SaaS application. If you have 100 clients using your software, you have 100 tenants.

Why use a shared database?

It's more cost-effective and easier to manage than having a separate database for each customer, especially when you have many customers.

What is 'row-level security' (RLS)?

It's a database security feature that ensures each user or customer can only see or modify the rows (records) that belong to them.

Details

Original description by the author

Design and implement multi-tenant SaaS architectures with row-level security, tenant-scoped queries, shared-schema isolation, and safe cross-tenant admin patterns in PostgreSQL and TypeScript.

repo: sickn33/agentic-awesome-skills

Popularity

GitHub stars
48k
Ranking position
#4041
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills