Getting started with multi-tenancy on Rails
04 Jul 2016
"I've already searched the whole internet, but I am stumped on how to get SaaS right."
Are you finding yourself in this position right now? Want to take on that SaaS contract but not sure if you can do it?
Well, you can! In this post, I'm going to list a few things you should consider and provide pointers to helpful resources on each one.
Subscriptions
Recurring revenue is the cornerstone of SaaS applications. It's been difficult to process payments until a few years ago.
Since then, a lot changed. Taking money, on schedule, is now more accessible than before.
First thing you'll need is to pick a payment solution provider:
They are both made by developers, for developers. A lot of subscription logic is already provided by those. You only need to plug these into your project.
In addition to credit cards, both work with Apple Pay and Bitcoin. Stripe also works with AliPay; Braintree with PayPal.
Now, where the integration comes in, both provide you with official Ruby bindings (stripe-ruby, braintree_ruby). Again, both are easy to configure, and the docs provide enough to get going.
If that feels barebone, there also is payola to make working with Stripe even simpler.
The libraries can only get you so far. Pete Keen, for one, has a book on some quirks and best practices of subscriptions.
Data model
Another important thing to consider is how you store your data. In a multi-tenant application, there usually exist accounts, which have some resources (like todos, or tickets, and so on).
A straightforward and practical way to model that is to think which resources are shared, i.e. accessible to everyone, and which are owned, i.e. available only to their "owner," for example.
Then, what you need to do is to set up foreign key from owned resources to their owner.
In practice, it usually means adding a user_id
/ account_id
field to your private resources.
Query these in your controller using a .where(account_id: current_account.id)
and it's good.
If doing that every time feels tedious, you can drop in some magic and make that work automatically: see the Multitenancy with Scopes Railscast for more info. Keep in mind, though, that a solution like this may not be the cleanest.
(An MSDN article on various approaches to multi-tenancy, including isolated databases.)
Subdomains
Finally, providing your users with a subdomain to access their stuff is quite common in SaaS applications, especially these where resources are owned by a team and not one user. The subdomain then acts as an entry point for the entire team.
To implement that in practice, you are going to need to:
- constraint your subdomain-specific resources into a
constraint
block - make your subdomain-specific controllers inherit from a
TenantBaseController
or something like that, which will automatically find an account for that subdomain - setup a wildcard DNS record so that subdomain requests to you your app
Other resources
Figuring all of that by yourself can be daunting, and while there are people who feel adventurous (like I did) and can get their hands dirty in all of that, there are some great resources that can guide you every step along the way:
- Multitenancy with Rails by Ryan Bigg will walk you through all the gotchas.
If you want to just get over with these, starter kits can be helpful:
- SaaS Rails Kit will provide you with a template package that already implements subscriptions