I'm truly baffled! There are probably 1000s of consumer (B2C) SaaaS example and OSS apps in virtually all languages. But there is virtually ZERO examples or OSS projects that talk about B2B multi-tenant apps! The worst part is that even companies like Google Cloud don't provide an example.
What I'm looking for is: A SaaS app that allows people to create tenants (companies), and allows admin of the tenant to login and manage group of users, keep track of billing for each tenant, have super-admin who can access any tenant. But the rest of the app code is shared across the tenants. I'm looking for code that's either in Java or JavaScript(NodeJS). Are you in the same boat as me? If not, could you please point me to something? I really appreciate that!
Once you’ve done that, you don’t have to worry about forgetting a `WHERE tenantId = foo` somewhere and leaking data. The actual code is shared (i.e. not installed separately or in separate processes) and you would simply use your dependency injection or equivalent to resolve the DB connection contingent on $user’s validated claims.
“Networking” or sharing entities across tenants becomes harder this way.. but purer/cleaner. You essentially create a federation layer and communicate across instances via a hard code wall (via network requests to yourself and an API) rather than “in memory” which is less efficient and requires a lot of boiler plate, but it’s going to be what you’re going to end up doing anyway.
using multiple schemas becomes a nightmare when you want to perform a migration to alter the database schema. you have to somehow perform a migration across every single schema without breaking anything. god forbid you need to rollback. have everything in one database makes it really easy. as please, don't talk how using a single database restricts scaling later on. with how far databases have come and how cheap cloud computing is, scaling isn't an issue anymore.
While that is true for simple queries it is not a valid statement for secure multi tenancy.
For example in this scenario: Account (Id). Order (Id, AccountId, CustomerId). Customer (Id, AccountId). You need to ensure Order can only use CustomerId that belongs to Account.
Rails does not include support for restricting deep relationships (grand children) to an account. Basically an attacker can misuse foreign keys from other accounts in new records (add a CustomerId from another Account on Order) or read data in relationship queries when initiating objects (show customer info from another account in an order).
There are ways of mitigating this but it requires doing more complex manual validation methods.
> using multiple schemas becomes a nightmare
There are gems that will solve some of this complexity but it is a risk. The most popular one is somewhat unmaintained.
E.g for the JVM, there's Liquibase and Flyway, and I agree with you, setting that up took a good part of a couple of weeks of dedicated effort.
So for simple queries, fine, but anything else this won't work.
https://influitive.io/our-multi-tenancy-journey-with-postgre...
Then they realise they've got a growing number of databases and webservers to maintain and account for, so they combine them all into a multi-tenant system.
I found a few tools early on that work for this in Rails. You can guarantee all of your sql includes the tenant.
- Apartment
- Tenancy
There's also several for the PHP ecosystem.
I've only done this at one company, and they self-hosted, and it was indeed a complete nightmare to manage, but part of that was the self-hosting part.
Interested?
And then providing enterprise service for large companies that want their own installation.
Everyone below a certain scale. Or when it just makes more sense, like Proboards' free tier.
Their approach has scaled to millions of concurrent users, but admittedly not helpful if you’re looking for a guide since the code is buried in a legacy monolith.
Part of the reason there isn’t a generic guide to this is that multi-tenancy is probably a premature optimization if a generic guide would be helpful. Just use nested user accounts to accomplish your business logic. By the time you really need true multi-tenancy, generic sample code won’t be much more helpful than the docs of the various plugins like Switchman.
1: https://github.com/instructure/canvas-lms 2: https://github.com/instructure/switchman
Feathers JS has got builtin authentication and it is easy to add tenants. I've created a quick example and published it here [1], there maybe some rough edges, please mail me if you have any questions.
As others have mentioned with multi tenancy you must have good test cases that verify you've appropriate filters in place to avoid leaking data.
[0] https://feathersjs.com/ [1] https://github.com/bjacobt/feathers-multi-tenant-example
I'm also happy to walk you (or others in the thread if time permits) though the source code of a closed source app I have over a video call if you need to grok the mechanics/db structure. (email in profile.)
It's got:
- multi-tenancy
- roles with-in each tenant
- sub-tenants (think engineering team vs accounting team vs hr team)
- accounts can be members of multiple tenants
- billing for each tenant (even sub tenants or inherit from root tenant)
- Super Admin & "Staff" roles
- Auditing
If anyone's interested in the open source app, follow here - https://twitter.com/tools_hub
[1] - https://stripe.com/blog/stripe-home
https://github.com/Internal-Tools-Hub/CorpHome/blob/master/R...
https://github.com/userdashboard/dashboard
Dashboard powers the basic 'web app with registrations' and then using modules it can be supplemented with organizations, Stripe Subscriptions and Stripe Connect to standardize / reuse the "SaaS boilerplate". It runs parallel to your application server so you can use whatever stack you like. Users browse your Dashboard server URL and it proxies your application server for content.
The software is complete but it needs niceties like useful charts and information added to the UI and I'll be prioritizing that in the coming weeks. It's got a really nice documentation site being generated with Github Actions but it's not publishing correctly unfortunately, probably tomorrow that will be resolved.
There are plenty of paid products in every language which are basically B2B SaaS templates.
ABP, bullettrain, Laravel etc.