Basic understanding of multi tenancy in rails
Multi-tenancy in Rails refers to the capability of a single instance of a Rails application to serve multiple, isolated tenants (i.e. separate customers or organizations) using the same codebase and infrastructure. Each tenant has its own set of data, which is stored in separate databases or schemas, and they cannot access or interfere with each other's data.
A multi-tenant Rails application is typically designed to allow tenants to customize certain aspects of their instance, such as branding, themes, and feature configurations. To implement multi-tenancy in Rails, you can use a gem such as Apartment to manage multiple databases or schemas and switch between them based on the tenant identifier.
In a multi-tenant Rails application, tenants are typically identified by a unique identifier such as a subdomain or a path in the URL. The tenant identifier is used to switch to the appropriate database or schema for that tenant, and all subsequent requests for that tenant are processed using the data from that schema.
Multi-tenancy has several benefits, including cost savings, improved scalability, and enhanced security. By running multiple tenants on a single instance of an application, you can reduce the costs associated with hosting and maintaining separate instances for each tenant. Multi-tenancy also allows you to scale your application more easily, as you can add new tenants without having to provision new hardware or infrastructure. Additionally, multi-tenancy helps to improve security by isolating data between tenants, reducing the risk of data breaches and ensuring that each tenant's data is secure.
To set up a basic multi-tenant architecture in Rails 7, you can follow these steps:
Add the Apartment gem to your Gemfile:
gem 'apartment'
Run bundle install.
Create a Tenant model:
rails g model Tenant name subdomain
Add the tenant identifier column to each table:
rails g migration AddTenantIdToUsers tenant_id:integer
Configure Apartment in an initializer:
Apartment.configure do |config|
config.excluded_models = %w[Tenant]
config.tenant_names = lambda { Tenant.pluck(:subdomain) }
end
Use the tenant identifier to switch between schemas in your application:
class ApplicationController < ActionController::Base
before_action :set_tenant
private
def set_tenant
tenant = Tenant.find_by(subdomain: request.subdomain)
Apartment::Tenant.switch(tenant.subdomain) if tenant
end
end
With these steps, you have set up a basic multi-tenant architecture in Rails 7 that allows you to run multiple instances of your application, each with its own set of data, on a single codebase and infrastructure.
We can also create with Rails API
Create API endpoints for tenants:
class TenantsController < ApplicationController
def create
tenant = Tenant.create!(tenant_params)
Apartment::Tenant.create(tenant.subdomain)
render json: { message: 'Tenant created successfully' }, status: :created
end
private
def tenant_params
params.require(:tenant).permit(:name, :subdomain)
end
end
With these steps, you have set up a basic multi-tenant architecture in a Rails API application that allows you to serve multiple tenants with a single codebase and infrastructure, each with its own set of data. The tenant identifier (subdomain) is used to switch to the appropriate database or schema for that tenant, and all subsequent requests for that tenant are processed using the data from that schema.
Create sign up and login pages for tenants
class TenantsController < ApplicationController
def new
@tenant = Tenant.new
end
def create
tenant = Tenant.create!(tenant_params)
Apartment::Tenant.create(tenant.subdomain)
redirect_to root_url(subdomain: tenant.subdomain)
end
private
def tenant_params
params.require(:tenant).permit(:name, :subdomain)
end
end
Multi-tenant architecture can be used in various applications in Rails, including:
SaaS (Software as a Service) applications: Multi-tenancy is a common design pattern for SaaS applications, as it allows you to serve multiple customers or organizations with a single instance of the application.
Marketplace applications: Multi-tenancy can be used to support multiple vendors or sellers in a marketplace, where each vendor has its own set of data and cannot access or interfere with the data of other vendors.
Enterprise applications: Multi-tenancy can be used in enterprise applications to support multiple departments or subsidiaries, each with its own data and configurations.
Educational applications: Multi-tenancy can be used in educational applications to support multiple schools or institutions, each with its own data and configurations.
Healthcare applications: Multi-tenancy can be used in healthcare applications to support multiple healthcare providers, each with its own set of data and configurations.
These are just a few examples of where multi-tenancy can be used in Rails. The key advantage of multi-tenancy is that it allows you to serve multiple customers or organizations with a single instance of the application, reducing the costs and complexity associated with maintaining separate instances for each customer.
Here is a detailed code example for a multi-tenant healthcare application in Rails:
Add the Apartment gem to your Gemfile:
gem 'apartment'
Run bundle install.
Create a Hospital model:
rails g model Hospital name
Add the tenant identifier column to each table:
rails g migration AddHospitalIdToPatients hospital_id:integer
Configure Apartment in an initializer:
Apartment.configure do |config|
config.excluded_models = %w[Hospital]
config.tenant_names = lambda { Hospital.pluck(:name) }
end
Use the tenant identifier to switch between schemas in your controllers:
class ApplicationController < ActionController::Base
before_action :set_tenant
private
def set_tenant
hospital = Hospital.find_by(name: request.subdomain)
Apartment::Tenant.switch(hospital.name) if hospital
end
end
Create sign up and login pages for hospitals:
class HospitalsController < ApplicationController
def new
@hospital = Hospital.new
end
def create
hospital = Hospital.create!(hospital_params)
Apartment::Tenant.create(hospital.name)
redirect_to root_url(subdomain: hospital.name)
end
private
def hospital_params
params.require(:hospital).permit(:name)
end
end
Create the Patients table for each new hospital that signs up:
class CreatePatients < ActiveRecord::Migration[6.0]
def change
create_table :patients do |t|
t.string :first_name
t.string :last_name
t.string :email
t.integer :hospital_id
t.timestamps
end
end
end
Create the Appointments table for each new hospital that signs up:
class CreateAppointments < ActiveRecord::Migration[6.0]
def change
create_table :appointments do |t|
t.datetime :date_time
t.integer :patient_id
t.integer :hospital_id
t.timestamps
end
end
end
With these steps, you have set up a basic multi-tenant healthcare application in Rails that allows multiple hospitals to sign up and use the application, each with its own subdomain and data
The tenant identifier (subdomain) is used to switch to the appropriate database or schema for that hospital, and all subsequent requests for that hospital are processed using the data from that schema. When a new hospital signs up, the Patients and Appointments tables are created for that hospital within its own schema, and all data for that hospital is stored and processed within that schema.
Top comments (5)
Hello,
Congrats for writing a series of posts about multi-tenant architecture in Rails.
I am happy to read more resources about this and thank you for contributing to Ruby community.
Hope you don't mind a suggestion: you can have better syntax highlighting if you specify the language when writing code samples.
For example for Ruby if you type
ruby
after the code markdown it will highlight the Ruby syntax:Writing this:
will generate this preview:
More details about how to do syntax highlighting in the markdown used by Dev.to can be found here
I was not sure how to contact you privately to write this suggestion so please feel free to delete this comment as it is off-topic.
Hello @lucianghinda
Thanks for reading my article i hope you like it and please let me know if i have made any mistake,
I have updated my blogs with ruby, please take a look once.
Let's stay connected.
Hi Everything fine, but to create tenants lot of articals, but i need how to point or update tenant to tenant own domain
for example tenant.dev.to, but owner hving own domain like customerowndomain.com
how to do it
how can i accive each tenant has one remote database
We are stiuck as ros-apartment gem does not work with rails 7.1 and still on 7.0