Readit News logoReadit News
Posted by u/node-bayarea 5 years ago
Ask HN: How come there is no example code for B2B-SaaS apps?
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!

ComputerGuru · 5 years ago
In my experience, a lot of projects start off with shared tenancy (using a tenant id discriminator in the database) and eventually migrate to completely separate schema for each tenant (i.e. a separate “installation” of a single-tenancy app for each tenant) to avoid security and architectural pitfalls.

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.

thrownaway954 · 5 years ago
using an ORM it's very simple. once you setup the relationships between models, you always use the highest level model as the entry point of your query and the ORM will scope the query for you. ie in Rails, if your highest level model is Account you just always use @account.customer.find(18). the Rails ORM will automatically scope the query to the current account.

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.

sleepyhead · 5 years ago
> the Rails ORM will automatically scope the query to the current account.

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.

hackerm0nkey · 5 years ago
I come more from a JVM world. But aren't there any DB migration/refactoring tools in Rails to allow for changes to propagate across tenants ?

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.

HatchedLake721 · 5 years ago
The highest level entry point makes so much sense. I’ve been building multitenant saas for last 3 years enforcing “where tenant = x” and you’ve just blown my mind.
mattmanser · 5 years ago
You can't really write reports or BI dashboards in ORMs, unless you want terrible performance.

So for simple queries, fine, but anything else this won't work.

gfodor · 5 years ago
Interestingly, I've only seen the opposite, going back to the 90s. Eventually managing N schemas ends up being difficult, and you're also fighting against the database.
awinder · 5 years ago
Yeah 100%. Multi-tenant as implemented this way with separate infrastructure works ok for very small values on N. Once you’re into N > 100s or 1000s then you’re absolutely not reducing complication.
forgingahead · 5 years ago
Are separate schemas really the right way to handle this? The folks who wrote the Apartment gem for Rails, a multi-tenancy solution that works on separate schemas, wrote about some troubles when scaling:

https://influitive.io/our-multi-tenancy-journey-with-postgre...

gitgud · 5 years ago
In my limited experience, companies start with single-tenancy apps. Get a client interested in their own private version, so they spin-up another instance.

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.

smileysteve · 5 years ago
> you don’t have to worry about forgetting a `WHERE tenantId = foo

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.

mattmanser · 5 years ago
Its a while ago now and I have no idea what post it was for, but there was a discussion here on HN about how this is a terrible idea as it turns into a complete mess and a nightmare to manage.

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.

Joeri · 5 years ago
On the enterprise software I worked on (IWMS system) we did both. Customers got their own schema, but big customers would give each branch their own virtual tenant within that schema. We started out with only the multiple schemas approach and ended up retrofitting a bunch of multitenancy features.
mguerville · 5 years ago
Thanks for this clear explanation. I’m a non developer currently experimenting with no code apps, I’m using userid filtering to segregate data between users and it feels “wrong” but it’s reassuring to see that it’s a pretty normal starting point before having a more mature architecture
Roritharr · 5 years ago
I'm contemplating writing an article about "things that are bad but you should absolutely do anyway when you start" to help with this analysis paralysis.

Interested?

JamesBarney · 5 years ago
The approach I've used and seen the most often is enforcing the tenancy at the ORM level so someone can't forget a where.

And then providing enterprise service for large companies that want their own installation.

TekMol · 5 years ago

    WHERE tenantId = foo
You only need to do that if you keep multiple tennants in one table. But who does this? Usually in a multi tennant application you have only one line which connects to the tennants DB and thats it. The rest of the code does not have to think about tennants.

hombre_fatal · 5 years ago
> But who does this

Everyone below a certain scale. Or when it just makes more sense, like Proboards' free tier.

excid3 · 5 years ago
I've been working on something like this for Ruby on Rails in case anyone is interested. It has multitenancy, billing separate for each tenant, automatic query filtering for the current tenant, etc. https://jumpstartrails.com
schappim · 5 years ago
I 2nd https://jumpstartrails.com . I purchased the "Unlimited Site License", and it is well worth it.
node-bayarea · 5 years ago
I wish there was something like this ready in Noode.js world (happy to pay)
petargyurov · 5 years ago
Intereting. I've been thinking about doing something like this with Python (Flask/Django), albeit a bit more general.
czue · 5 years ago
I work on https://www.saaspegasus.com/ as a similar project for Django. Let me know if you have any questions!
bnt · 5 years ago
For the unfamiliar, OP makes awesome Rails tutorial videos and is really knowledgeable on the subject.
guptaneil · 5 years ago
One of the largest open-source Rails apps has all of those features: Canvas LMS[1]. It uses Switchman[2] for abstracting the multi-tenancy logic.

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

yodon · 5 years ago
That said, Canvas is also AGPL 3 which might be a concern for some people looking for code to base their new SaaS startup on.
node-bayarea · 5 years ago
Nice. It's amazing so many Rails multi-tenant projects but almost nothing in the Node.js world
tasssko · 5 years ago
Try this https://saasstartupkit.com/ built in Golang. My company has used it for a proof of concept as it definitely is built around b2b multi-tenancy. Good starting point for us at the time.
node-bayarea · 5 years ago
thanks!
bjacobt · 5 years ago
You should look into Feathers JS [0]. You've the option to write in Javascript or Typescript and its built on top of nodejs/express.

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

node-bayarea · 5 years ago
Thanks, will look into it
masonhensley · 5 years ago
I know it's a little early and it will be in Ruby on Rails. However, I'm working on open sourcing a clone of Stripe's Home [1] as part of a series of open source B2B applications & they should check all those boxes (besides the Java/Node)

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

hackerm0nkey · 5 years ago
Interested to see how you guys approached that for a Java B2B service. Thanks for the offer.
dchuk · 5 years ago
I’m super interested in this, but not sure what I’m looking at at the twitter account. Is there something on github or similar to look at?
masonhensley · 5 years ago
Ya, sorry. The twitter account is a placeholder while we work. Just spun up a repo you can follow.

https://github.com/Internal-Tools-Hub/CorpHome/blob/master/R...

benologist · 5 years ago
I have been working on this:

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.

james_s_tayler · 5 years ago
http://abp.io/ is probably the best open source one I've seen. They also offer a paid product which is fairly comprehensive. I don't quite like their frontend stuff but the backend side of things is definitely what you're looking for.

There are plenty of paid products in every language which are basically B2B SaaS templates.

ABP, bullettrain, Laravel etc.

node-bayarea · 5 years ago
looks great, I wish there was something like this in the Node.js world