Skip to main content

Multi-tenant SaaS boilerplate with Next.js, Prisma and tRPC

Multi-tenant isolation, tested, not promised

Multi-tenant,
not just promised. Backed by tests.

Most boilerplates add an organizationId column and leave the filtering to you. HeartCo automates reads, keeps writes to one explicit rule, and ships the tests that prove it.

6
auto-scoped Prisma operations
12
security test files
8
RBAC roles
160+
Prisma models

How the isolation works

One Prisma extension for reads, one simple rule for writes.

Reads, filtered automatically

ctx.orgDb adds organizationId to findMany, findFirst, findFirstOrThrow, count, aggregate and groupBy. Nothing to write, nothing to forget.

Writes stay explicit, on purpose

create, update and delete are not covered by the automatic filter: organizationId has to appear in the where clause by hand, easy to check in review.

findFirst, never findUnique

findUnique only accepts unique fields in its where clause, so the org filter cannot be added to it. One rule, easy to grep for.

Sub-entities through the parent

An invoice line has no organizationId of its own: the filter goes through the relation to the invoice, never through the line's ID alone.

IDOR: NOT_FOUND, never FORBIDDEN

A resource from another organization comes back as missing, not refused. A refusal confirms a valid ID exists somewhere else.

RBAC as a matrix

Isolation protects the boundary between organizations. A per-role permission matrix protects the boundaries inside one.

What the isolation covers, and what it doesn't

Most product pages stop at the first table. Here's the second one.

Automatic

What ctx.orgDb filters

  • Reads on models registered as organization-scoped
  • findMany, findFirst, findFirstOrThrow, count, aggregate, groupBy
  • The same way in every router that uses ctx.orgDb
Explicit

What stays on you

  • Every write: create, update, delete
  • findUnique, deliberately left out of the automatic filter
  • Registering a new model as organization-scoped
  • Direct access through ctx.db (webhooks, scheduled jobs, admin tooling)

The tests that ship, not a promise

Twelve security test files that come with the code, not a checklist you write yourself.

Cross-tenant isolation

Two mocked organizations, every sensitive read (invoices, quotes, conversations) checked on its own.

IDOR by domain

One dedicated file per sensitive surface: accounting, conversations, messages, notifications, third-party integration events.

An audit that walks the schema

One generic test checks that every scoped model goes through the automatic filter, not just the models already covered by hand.

Who this is for, and who it isn't

This is for you if
  • You're building a B2B SaaS where one organization has several users
  • A data leak between two customers would be an incident, not a footnote
  • You want tests that ship with the code, not an architecture to design alone
Not for you if
  • Your product is single-tenant, with no notion of an organization
  • You'd rather isolate with a separate database per customer

The isolation code, not just the pitch.

Prisma, tRPC, the security tests: all in the repo, from day one.

Multi-tenant SaaS boilerplate for Next.js | HeartCo