MOURABUILD
// Architecture5 min

One system, many clients, without turning into a mess

How a single system serves many companies without mixing anyone's data, and what breaks when the first big client arrives.

01

The problem multi-tenancy solves

Multi-tenant is when the same system serves several clients and each one only sees their own data. It sounds like a technical detail, but it's a business decision: it's what separates selling software from selling the same software fifty times.

The alternative is spinning up a copy per client. It works for the first three and becomes hell at the tenth, when you need to ship a fix and you have ten servers, ten databases and ten slightly different versions.

02

Three ways to isolate, and the price of each

A database per client is the strongest isolation and the most expensive to maintain: every migration runs N times and any report that crosses clients becomes manual work.

A schema per client is the middle ground, and at scale it's often the worst of both worlds: you still multiply migrations, but you've already lost the simplicity of a single database.

A client column on every table is what I use in most cases. The migration runs once, the report is one query, and isolation comes down to discipline in data access, which is where the risk lives.

03

The mistake that leaks data between clients

With a client column, leaks don't happen through break-ins. They happen through forgetting: a query without the client filter, in a report nobody reviewed, and suddenly one client sees another's numbers.

That's why the filter can't depend on the developer remembering. It has to live in the layer that reads the database, applied by default, so that querying without a client set is an error, not an oversight. If your database supports row-level policies, even better: the rule lives next to the data.

04

A single address

A subdomain per client looks professional and charges you later: certificates, DNS and a pile of odd cross-domain login cases.

I prefer a single address, with the client resolved after login. Whoever needs their own branding gets it on screen, not in the URL. And when someone truly needs their own domain, then it's worth the work, for that client.

05

What breaks when the big client arrives

While everyone is small, everything feels fast. The first high-volume client reveals what was hidden: a query without an index on the client field, a report that scans the whole table, and heavy work running inside the request instead of in a queue.

None of that is hard to fix, but it's much cheaper to fix early, while you can still change the data format without telling anyone.

06

How I build it today

A single database with a client column, the filter applied in the access layer, a composite index starting with the client, one address and heavy work in a queue. That's what runs in Fluxnavi and in what I build for clients.

If you're building a SaaS right now, this is the cheap moment to get it right. After a hundred clients, changing the isolation is a migration, not a decision.

Got a live system with no owner?

I take over what someone else started, fix what's leaking and carry on from there.

Let's talk on WhatsApp
Next article: Taking over another developer's code without breaking what's live →