Fóir for SaaS
Your product is one schema serving a lot of customers, and most of the work is keeping their data apart. In Fóir the schema is shared on purpose, and the isolation is not something you write.
One schema, and one place to change it
Multi-tenancy usually forces a choice: one schema every customer has to move with at once, or a fork per customer that nobody can safely change a year later.
In Fóir a model is defined once, on your project, and every customer's organisation inside it inherits it. There is one definition rather than a copy per customer, so editing it changes what all of them serve. A customer can define a model of their own beneath yours without forking the rest of your schema.
A shared schema is not shared data
The failure you cannot afford is one customer reading another's rows, and in most stacks the only thing standing in the way is a clause somebody remembered to write.
Each customer is an organisation inside your project, and every row they write is stamped with it in the database. Access is enforced by Postgres underneath your application rather than by whichever code path is running, so a request that names no customer comes back with none of their rows rather than all of them, and a new place to put data cannot ship without rules covering it. No read or write in your code names the customer. The credential it runs on decides, so a query cannot be pointed at the wrong one.
Standing a customer up is an API call
Signing a customer up usually means a provisioning script that creates a tenant, brands it, seeds it, and leaves half of that behind when a step fails.
One call stands the customer up, keyed by an id you choose for them. It creates their organisation with its branding, and can write their settings, add their first member and mint a key confined to them. They inherit your models at once, with no schema to copy into place. Call it again with the same id and it resumes at the step that did not complete instead of creating a second customer.
What your largest customer will ask
The deal that moves you upmarket arrives with a security review, and the honest answer is usually a diagram of intentions.
Isolation here is a database mechanism rather than a policy. Their users sign in on a domain they own, on screens carrying their name rather than yours. And if they ever ask for their data, an export taken as their organisation holds their rows and no other customer's, because the rule that confines every read confines the export too.
What every customer starts with
The parts of a multi-tenant product you would otherwise build once and maintain forever.
Sign-in for their users
Registration, password, one-time code, social and OIDC, on a domain the customer owns.
Their name on it
Logo, colour, sender name and support address per organisation, used by the screens and emails their users see.
A key per customer
A key confined to one customer cannot be steered anywhere else, whatever the request says. Your back office holds one key and names the customer per request.
Roles inside their account
Customer roles you declare in config, so your customer's own team has admins and members without you building a permission system.
Meter what they use
Quota an operation per customer on a rolling window, and gate it on the segment they are in, using the same audiences that personalise their content.
Environments in the same shape
One config names a staging project and a production project, so a schema change is rehearsed somewhere safe before it reaches customers.
Usage per customer
Records, media, active users and email counted per organisation, each with a cap you can set, so you can see and limit what each customer uses.
Background work
Operations, schedules and event hooks per organisation, with retries and a record of what happened.
Media
An asset library with transformations and responsive renditions, and access rules over files.
Model it once, then add the second customer
Create a project and push the models your product runs on. The next customer is an organisation inside it.