Multi Tenancy logo

Multi Tenancy

Community
MartinOlivero
multi-tenancy

This skill should be used when several customers, organizations, teams or workspaces share one application and their data must stay apart — and especially when a person can belong to more than one of them. Trigger phrases (English) include "multi-tenant", "organizations and members", "workspaces", "teams", "invite users to an org", "a user in two companies", "switch workspace", "agency with several clients", "tenant isolation", "demo account", "white label". Trigger phrases (Spanish) include "multi-tenant", "varias empresas en la misma app", "organizaciones y miembros", "invitar usuarios", "un usuario en dos empresas", "cambiar de espacio", "cuenta demo", "que un cliente no vea los datos de otro". It decides the membership model before the schema hardens, puts the tenant rule in one place, and covers the edges that leak — server functions, deletion, invitations and the shared demo. Use `data-modeling` for the schema itself and `rls-audit` to verify the policies.

Overview

PublisherMartinOlivero
Repositorysaas-builder
Skill namemulti-tenancy
Stars
4
Forks
2
Bundled files
1
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by MartinOlivero on GitHub. Read the source before you install it.

Installation

Install the Multi Tenancy AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/MartinOlivero/saas-builder/tree/main/skills/multi-tenancy
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/MartinOlivero/saas-builder.git /tmp/saas-builder
mkdir -p .claude/skills
cp -r /tmp/saas-builder/skills/multi-tenancy .claude/skills/multi-tenancy
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Multi Tenancy in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Multi Tenancy on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Multi Tenancy is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Multi-tenancy

Tenant isolation is one rule — "you only touch what belongs to an organization you are in" — that must hold in every query, every server function and every screen. This skill is about writing that rule once and about the places it is forgotten.

Analogy: an office building with several companies. The lobby is shared, each floor is private. The security model isn't a guard on every desk — it's one badge system that every door consults. The failures are never the front doors; they are the service elevator, the cleaning contractor with a master key, and the show floor left open for visitors.

Discovery (max 3 questions, only if unknown)

  1. Can one person ever belong to two organizations — a freelancer, an agency, a consultant, a founder with two companies?
  2. Who creates an organization — anyone who signs up, or only you?
  3. Is there a shared demo or sample account that strangers can enter?

Step 1 — Decide the membership model now

ModelShapeChoose when
Single-orgusers.org_idThe answer to question 1 is a certain, permanent no
Membershipsmemberships(user_id, org_id, role) + an active-org selectionAny doubt at all

Default to memberships. The single-org shortcut saves a table today. Converting later, in one production app, meant touching 39 of 56 policies, 21 functions and 33 files — and exposed the side effects in Step 4.

Step 2 — One choke point

Every policy and query asks one function for the caller's tenant — current_org_id() — instead of reading a column directly.

  • With memberships it returns the active organization, after checking the caller is really a member of it.
  • Because everything goes through it, changing the model later changes one function.
  • The role check lives beside it and filters by the caller's id. Never ask "is there an admin row?" — the first row returned belongs to someone.

Step 3 — "What I can see" is not "who is on the team"

These are two different questions, and conflating them is the commonest bug after a membership migration.

  • What I see follows my active organization.
  • Who is on the team is everyone with a membership in this organization, whatever they have open right now.

List teams from the memberships (a team view), never from a per-user "current org" field — otherwise a person working in their other company vanishes from user lists, assignment rules and public booking pages.

Step 4 — Shared people: decide each of these explicitly

Once a person can be in two organizations, each of these has a wrong default:

  • Deleting an organization must not delete its people. Check the ON DELETE of every foreign key between org and person.
  • "Remove user" removes a membership. The account is deleted only when the last one goes.
  • Profile fields (name, working hours, avatar) — can the admin of A edit them for someone shared with B? Usually: per-membership settings belong to the membership, identity belongs to the person.
  • Per-person integrations (a connected calendar, a personal API key): which organization's data do they sync into?
  • Revoked access: is the login disabled, or only the membership? Leaving the auth user alive keeps the password valid; re-inviting then collides with "email already exists".
  • Invitations: a link opened while signed in as someone else should say so, not bounce to the dashboard. And a failed read while accepting is an error — never "this user has no organization", which can move a person out of the one they had.

Step 5 — The service elevator: code that bypasses RLS

Anything running with a service key or as SECURITY DEFINER skips the policies. That code must apply the tenant rule itself:

  • Take the tenant from the verified session, never from the request body or a function parameter.
  • Add the tenant to every join and lookup inside it. A background job with the admin key that forgets one filter writes to another customer's client.
  • Enforce "same tenant" in the schema with composite foreign keys — (tenant_id, id) referenced as a pair — so a row cannot point at a parent in another tenant even when code forgets.
  • Use one server-side gate for "may this caller act here?" (active user, valid membership, current subscription). Then test that the server gate and the screen's own check agree for every role — two gates drift.

Step 6 — The front door: who can create a tenant

Closing the sign-up page does not close sign-up. If a function creates an organization, it can be called directly — in one app, three strangers created organizations the same day through social login after the registration screen had been removed.

  • Protect the function that creates the tenant, not the page that calls it.
  • Get notified on every new organization.

Step 7 — The show floor: a shared demo is a hostile tenant

A demo that visitors enter is an account controlled by strangers. Assume they will try every button and every API call.

  • Block spend: no paid AI calls, emails or messages from the demo.
  • Block writes that persist: no changing or disconnecting keys, no inserting or deleting shared records.
  • Enforce in the server and in the policies ("the organization is not the demo"), not by hiding buttons.
  • Fail closed: if the code cannot tell whether this is the demo, refuse.
  • No shared password in the bundle. Issue a personal link that expires.
  • Demo data ages. Seeded dates drift into the past; re-date them on a schedule, including derived columns the dashboards filter by.

Step 8 — Tenant settings that are easy to forget

  • Time zone is tenant (or user) data, and something must write it. A default nobody sets puts everyone in UTC: slots offered at five in the morning, two people seeing different times for the same appointment, day boundaries that cut off the evening.
  • Rate limits and quotas per tenant, especially on public endpoints where you cannot rely on the visitor's IP.

Handoff

Pass the membership model and the choke-point function to data-modeling (schema and indexes led by tenant_id), auth (roles), and rls-audit (verification from outside). Run rls-audit after any change to this model.

Output

Deliver: the membership decision with its reason, the tables, the current_org_id() function and role check, the team view, the explicit answer to each item in Step 4, the server gate, the tenant-creation guard, the demo restrictions if there is one, and the cross-tenant tests (user of A acting on B, through the API and through each server function).

Field notes

references/field-notes.md — the migration and the leaks these steps came from.

Reference

PostgreSQL docs (Row Security Policies, composite foreign keys), AWS "Multi-tenant data isolation with PostgreSQL Row Level Security", the multi-tenancy sections of your BaaS's documentation. Pairs with data-modeling, auth, rls-audit and secure-coding.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Multi Tenancy AI skill do?

This skill should be used when several customers, organizations, teams or workspaces share one application and their data must stay apart — and especially when a person can belong to more than one of them. Trigger phrases (English) include "multi-tenant", "organizations and members", "workspaces", "teams", "invite users to an org", "a user in two companies", "switch workspace", "agency with several clients", "tenant isolation", "demo account", "white label". Trigger phrases (Spanish) include "multi-tenant", "varias empresas en la misma app", "organizaciones y miembros", "invitar usuarios",...

Why use Multi Tenancy on TypingMind?

Because you install it once and use it with any model. Multi Tenancy is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Multi Tenancy in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/MartinOlivero/saas-builder/tree/main/skills/multi-tenancy. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Multi Tenancy?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Multi Tenancy?

As many as you like. As long as a model supports skills, you can use Multi Tenancy with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Multi Tenancy AI skill free?

Yes. It is published on GitHub by MartinOlivero under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇