DEV Community

Cover image for Set up a basic multi-tenant architecture in Rails 7 - 1
Harsh patel
Harsh patel

Posted on • Updated on

Set up a basic multi-tenant architecture in Rails 7 - 1

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
lucianghinda profile image
Lucian Ghinda

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:

Image description

will generate this preview:

Image description

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.

Collapse
 
harsh_u115 profile image
Harsh patel

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.

Collapse
 
ratnaraju profile image
Ratnam Raju

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

Collapse
 
suhelrana10 profile image
sohel rana

how can i accive each tenant has one remote database

Collapse
 
retail_realm_09053ff02197 profile image
Retail Realm

We are stiuck as ros-apartment gem does not work with rails 7.1 and still on 7.0