ActiveMultiTenant

Multi tenant applications are very common, having something out of the box to handle this would be really nice. Even if a full solution isn’t possible, every application is different, but maybe some tools to make it easier / help you do the right thing?

ex I usually add a validation that checks associations are also associated with the same tenant when created.

8 Likes

I wonder if there’s a better way to check how prevalent a thing is in our ecosystem. So far it feels to me like we’re all going by our gut feeling (I’m guilty of this as well by asking for a baked in admin framework for Rails). As for multi tenancy, this is what I can find Category: Multitenancy - The Ruby Toolbox . What do we make of the numbers, can we estimate if this means a majority of apps is using this?

1 Like

I’m not sure if it counts as “true” multi-tenancy but I think the accounts system in Basecamp is quite brilliant and would be broadly applicable to most B2B rails apps. I think it’s basically a rack middleware that’s scoping all routes to an account ID, which goes into current.rb etc. I’m a very inexperienced rails programmer, but this is one of those things I’d love to be baked in (as well some more tools for user authentication).

2 Likes

I know @eileencodes has some plans to get multi tenancy into Rails.

I agree that the current state of affairs is not perfectly ideal. The good news is that the internals of Rails and ActiveRecord are very multi tenant friendly. We have been using it for many many years at Discourse. The bad news is that you need a gem/special library.

At Discourse we use:

We run 100-300 customers on a single cluster, each customer has a dedicated database, all 100-300 databases are clones structure wise (so we can reuse schema cache) but have distinct data.

The one big pitfall we had to work through is keeping on top of all the connections, this involves both running pgbouncer and a custom connection reaper cause unfortunately atm every connection pool gets a dedicated thread to reap connections discourse/discourse.rb at 4601833e4ed98aaaaf90c0ddab2bfebfae42db7c · discourse/discourse · GitHub

We have to be really careful and measured moving towards a native multi tenancy story cause there are many dragons, some of which are not even under rails control. (PG performance suffers with 1000s of open connections for example)

8 Likes

Thanks for the link, I hadn’t come across rails_multisite before.

I think one of the challenges with something like this is there at a lot of different ways to implement it, all with different tradeoffs and pitfalls to avoid. We have the database per tenant approach you mentioned, you can use a schema per tenant (with Postgres at least) GitHub - influitive/apartment: Database multi-tenancy for Rack (and Rails) applications, at Shopify we put the account id on every table and scoped the queries automatically.

That being said I’m pretty sure there are useful building blocks from all of these and having them supported natively within rails would help developers make safer and better supported choices.

It also sounds like some work is already happening in this direction if @eileencodes is extracting some of their approach from Github which is awesome. I’m sure Shopify will be contributing something back for composite primary keys which will be another great building block https://twitter.com/jeremycole/status/1260305100863451136?s=21

6 Likes

Sharding support was implemented in Add support to `connected_to` and `connects_to` for horizontal sharding by seejohnrun · Pull Request #38531 · rails/rails · GitHub. We’ll be implementing auto-routing for shards in Rails 6.2. We’ll also be upstreaming the ability to support associations across shards/clusters by creating 2 queries instead of joining.

12 Likes

Abstracting out the process for associating across clusters will be life-changing for my current project. So excited. :smiley:

The work for associating across clusters is already done in a private gem at GitHub, we just need to extract it into Rails once we’re confident it covers most use cases. Should be released in 6.2 :smile:

14 Likes

@eileencodes thanks for all your work on this stuff! It’s so cool that we smaller shops can benefit from the path that Github and others have trod.

3 Likes

Think this is the one you’re referring to?

Unfortunately this solution that (at least to me) looked really promising at the beginning turned out to be quite dangerous at least on Heroku Heroku Postgres | Heroku Dev Center

My take is that either the tenant_id in every table + default_scope or the multiple DBs are the way to go for multi tenancy depending on the project situation.

Yes! It was cool to see DHH post that after my comment here. I hope somebody does flesh that out into a PR or gem or something.

I’m running this on Heroku. No issues yet with 20+ tenants. Then again my use case probably isn’t going to grow dramatically just yet.

Multitenancy is indeed a big feature, however there is no single-right way to implement it.

If you want schema-based multitenancy, Rails 6 already supports easy schema-switching.

If you want row-based multitenancy, there are more than enough good gems.

1 Like

I just released a new gem: multi-tenant-support which mainly focus on protecting data leak on ActiveRecord level for multi-tenant.