> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a multi-tenant / SaaS platform on top of Spree

> Set up Spree as a multi-tenant SaaS ecommerce platform — install the Enterprise gem, apply license keys, configure subdomains, and provision tenants.

<Info>
  Multi-tenancy requires [Spree Enterprise Edition license](https://spreecommerce.org/pricing).
</Info>

Spree can be configured to run a multi-tenant / SaaS platform. This guide will walk you through the steps to set up your Spree application to support multiple tenants (stores).
Each tenant (store) can have its own isolated data and configuration, including:

* customer accounts
* staff accounts (admin users), staff can manage multiple tenants (it's the standard invitation flow)
* products, categories, and other catalog data
* orders and order history
* shipping and payment methods
* tax rates and zones
* store settings (name, logo, etc.)
* etc.

All data is fully isolated besided the staff users, which can manage multiple tenants. This allows you to create a SaaS platform where each tenant can have its own store with its own branding and configuration. Isolation works across admin dashboard and API.

<Info>
  If you need individual seller/supplier/vendor accounts but shared product listings under one site you should use [multi vendor recipe](/developer/multi-vendor) instead.
</Info>

## Prerequisites

* You need to be on Spree 5.1+, we recommend using [CLI](/developer/getting-started) to setup your Spree application.
* You need to set 2 environment variables in your `backend` directory:
  * `KEYGEN_ACCOUNT_ID`
  * `KEYGEN_LICENSE_KEY`
* Both PostgreSQL and MySQL are supported

<Info>
  You will need to add these environment variables to your CI/CD pipeline and staging/production environments.
</Info>

## Installing gems

1. Add the following code to your `Gemfile`:

   ```ruby theme={"theme":"night-owl"}
   source "https://license:#{ENV['KEYGEN_LICENSE_KEY']}@rubygems.pkg.keygen.sh/#{ENV['KEYGEN_ACCOUNT_ID']}" do
     gem 'spree_enterprise'
     gem 'spree_multi_tenant'
   end
   ```

2. Install gems:

   <CodeGroup>
     ```bash Spree CLI (Docker) theme={"theme":"night-owl"}
     spree bundle install
     ```

     ```bash Without Spree CLI theme={"theme":"night-owl"}
     bundle install
     ```
   </CodeGroup>

3. Run generators:

   <CodeGroup>
     ```bash Spree CLI (Docker) theme={"theme":"night-owl"}
     spree generate spree_enterprise:install && spree generate spree_multi_tenant:install
     ```

     ```bash Without Spree CLI theme={"theme":"night-owl"}
     bin/rails g spree_enterprise:install && bin/rails g spree_multi_tenant:install
     ```
   </CodeGroup>

   <Info>
     This will copy and run migrations for `spree_enterprise` and `spree_multi_tenant` gems.
   </Info>

## Setting root domain

Usually multi-tenant applications are configured to use subdomains for each tenant. For example, if your root domain is `example.com`, you can have tenants like `tenant1.example.com`, `tenant2.example.com`, etc.
To make it work you need to set the `Spree.root_domain` in your `config/initializers/spree.rb` file, eg.

```ruby theme={"theme":"night-owl"}
Spree.root_domain = 'example.com'
```

or use environment variable:

```ruby theme={"theme":"night-owl"}
Spree.root_domain = ENV.fetch('SPREE_ROOT_DOMAIN', 'localhost')
```

This way you can also test it locally using `localhost` as root domain, and use `tenant1.localhost`, `tenant2.localhost`, etc. for tenants.

## Customer User Class adjustment

We need to make slight adjustments to the user class so it can work in a multi-tenant environment.

You need to remove `:validatable` module. This module is responsible for validating the user's email uniqueness. We need to change it to validate it in the scope of the tenant.

```ruby backend/app/models/spree/user.rb theme={"theme":"night-owl"}
class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :validatable # [!code --]
  devise :database_authenticatable, :registerable, # [!code ++]
         :recoverable, :rememberable, :trackable, :confirmable

  include SpreeMultiTenant::CustomerUserConcern # [!code ++]
end
```
