You are three clients into a B2B portal when the first security questionnaire lands. It asks, in eight different ways, whether one customer's data ever sits next to another's. Whoever owns the roadmap now has to pick an isolation model, and that decision is far cheaper in month two than in year two.
Four models, and what each one really costs you
- Shared schema, a tenant_id column everywhere. Every query filters on it, and Postgres row-level security enforces it even when a developer forgets. Cheapest to run, fastest to ship, and easiest to get wrong at the edges — background jobs, exports, search indexes, file keys.
- Schema per tenant. One Postgres database, a schema per client. Fine up to a few hundred tenants. Watch your connection pooler: PgBouncer in transaction mode breaks SET search_path, so you need session mode or per-tenant pools.
- Database per tenant. Clean blast radius, trivial per-tenant restore, easy to hand over on exit. Costs more, and every migration now runs N times.
- Instance or VPC per tenant. For the bank whose procurement team accepts nothing less. Price it as a separate SKU.
Where the build cost actually sits
In our experience the isolation logic is not the expensive part. A shared-schema build with RLS, tenant-context middleware, audit logging and tests typically lands in 3-6 weeks for a small team. What eats the next two quarters is everything around it.
- Propagating tenant context through queues, cron jobs and webhooks, where there is no logged-in user to read it from.
- Per-tenant backup, restore and deletion. If a client asks you to prove erasure under the DPDP Act, "we ran a DELETE with a WHERE clause" is not an answer.
- Support and analytics tooling that crosses tenants without leaking rows.
- Migration drift. With database-per-tenant, one failed migration at tenant 37 of 60 is a Tuesday you remember.
A worked number: 40 tenants on managed Postgres in ap-south-1. Shared schema on one db.t4g.medium with a replica runs roughly ₹9,000-14,000 a month and one migration. Forty separate instances — the honest version of database-per-tenant, with independent failure domains — is 40 sets of backups, monitoring and upgrade windows, typically ₹1.2-2 lakh a month, and every operational task multiplied by 40. If logical separation is enough, 40 databases on a single instance is cheap; if you need blast-radius isolation, you are paying for it.
What buying actually gets you
"Buy" means two different things and teams conflate them.
The first is buying the substrate. Managed Postgres with RLS, Supabase, Neon, Azure SQL elastic pools, or AWS's SaaS reference architectures hand you tenancy primitives you would otherwise write. Add an auth layer with organisations — WorkOS, Auth0 Organizations, Clerk, Zitadel — and membership, invitations and SSO stop being your problem. For most SMB-facing products that is the right trade: you pay someone else's maintenance bill instead of accruing your own.
The second is buying the application. If you need a CRM, an email marketing tool or a WhatsApp outreach pipeline, the isolation problem belongs to the vendor. Building your own multi-tenant CRM to dodge a per-user licence is rarely cheaper once you count two years of engineering.
Where buying quietly fails: pricing that scales per tenant or per MAU and turns your best customer into your worst margin; RLS policies that cover your database but not your S3 bucket, your search index or your logs; and the enterprise deal that wants a dedicated environment, which no shared platform will hand you on a Tuesday afternoon.
Data residency is now a sales question, not only a compliance one. Customers ask for ap-south-1 or a UK region, and if your platform choice cannot pin workloads to a region, you will discover that during procurement rather than before it.
A rule that survives contact
Start shared-schema with tenant_id on every row and RLS on, but keep one abstraction: a shard map that resolves tenant to database. Every query goes through it from day one, even when the answer is always the same database. That single seam lets you promote one nervous or oversized tenant to its own database in an afternoon rather than a quarter.
Three habits do the rest:
- Never read tenant_id from the request body or query string. Derive it from the authenticated session.
- Run one test that asserts Tenant A gets a 404 for Tenant B's record, on every new endpoint, in CI.
- Log tenant_id on every query you can, so incident reviews take minutes.
Where to start
Choose the model by the customer you are most afraid of losing, not the one you have today. If questionnaires are already arriving, shared schema plus RLS with a shard map is usually the right first stop, and it is weeks of work rather than months. We build multi-tenant portals and internal tools at Maysan Labs, and this is one of the first architectural conversations we have with every client — worth having before the schema hardens.
Buying software or a website?
Twelve questions to ask any vendor before you sign: price, your data, fit for an Indian business and support.
Get the free checklistWritten by Maysan Engineering Team at Maysan Labs, a software studio in Gurgaon, India. Follow us on LinkedIn