Multi-Tenant Laravel Apps with Tenancy for Laravel — A Beginner-to-Advanced Guide

Author

Kritim Yantra

May 06, 2025

Multi-Tenant Laravel Apps with Tenancy for Laravel — A Beginner-to-Advanced Guide

If you’re building a SaaS (Software as a Service) product with Laravel, where each customer has isolated data (like a CRM, School Management System, or Project Tool), you’ve likely come across the term multi-tenancy.

Multi-tenancy means one Laravel application serves multiple tenants (clients). Each tenant can have its own users, data, and even design.

In this guide, we'll learn how to implement multi-tenancy using the Tenancy for Laravel package, created by Stancl.


🧠 What You'll Learn

  • What is Multi-Tenancy?
  • Types of Tenancy: Single vs Multi-Database
  • Installing Tenancy for Laravel
  • Setting up Tenants (from scratch!)
  • Using automatic identification (subdomains, domains)
  • Creating tenant-aware routes and migrations
  • Managing tenant switching manually
  • Advanced features (Events, Central Models, Custom Tasks)
  • Real-world SaaS structure

🚀 What is Multi-Tenancy?

Imagine you're building an app like Notion or Slack. Each company (tenant) should:

  • Have their own users
  • Isolated data
  • But all tenants use the same codebase

This is where multi-tenancy comes in. You don't create a new Laravel project for each customer — you use one app and separate the data per tenant.


🔍 Types of Tenancy

Tenancy for Laravel supports two types:

1. Single Database (with tenant_id column)

All tenants share one database but their records are separated using a tenant_id.

✔️ Easy to set up
❌ Data not physically isolated

2. Multi-Database

Each tenant has a separate database.

✔️ Full data isolation
✔️ Better for large clients
❌ Slightly complex setup

We’ll focus on multi-database as it’s the most powerful and scalable.


️ Step 1: Installing Laravel and Tenancy Package

Let’s start from scratch.

composer create-project laravel/laravel multi-tenancy-app
cd multi-tenancy-app
composer require stancl/tenancy

Now publish the config file:

php artisan tenancy:install

This creates:

  • config/tenancy.php
  • Required migrations
  • Events
  • Routes setup

Run migrations:

php artisan migrate

🧱 Step 2: Creating the Tenant Model

Tenancy uses a Tenant model (stored in the central database) to store tenant metadata like domains.

You already have a tenants table created after install.

You can create a tenant like this:

use Stancl\Tenancy\Database\Models\Tenant;

$tenant = Tenant::create([
    'id' => 'acme', // Unique ID
]);

$tenant->domains()->create([
    'domain' => 'acme.localhost', // Map domain
]);

🎯 Tip: Use .localhost for testing subdomains locally.


🌐 Step 3: Local Subdomain Setup (for development)

To test subdomains locally, edit your hosts file:

127.0.0.1 acme.localhost
127.0.0.1 globex.localhost

Start Laravel server:

php artisan serve --host=localhost --port=8000

🛠️ Step 4: Migrating Tenant-Specific Tables

To isolate tenant data, you need tenant-specific tables (e.g., users, projects, etc.).

Create a migration using:

php artisan tenancy:make:migration create_users_table

It will be saved in database/migrations/tenant/.

Example:

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamps();
});

Now run it for all tenants:

php artisan tenants:migrate

✨ Step 5: Auto Identification by Domain

Tenancy will automatically detect the tenant based on the subdomain or domain.

You can configure this in config/tenancy.php:

'identification_middleware' => [
    \Stancl\Tenancy\Middleware\InitializeTenancyByDomain::class,
],

You can also use InitializeTenancyBySubdomain.


🧪 Step 6: Creating Tenant Routes

By default, routes inside routes/tenant.php are only accessible under tenant domains.

// routes/tenant.php
Route::get('/', function () {
    return 'Tenant Home: ' . tenant('id');
});

Visit:
http://acme.localhost
It will show: Tenant Home: acme


🏗️ Step 7: Seeding Tenant Data

To create seeders for tenants:

php artisan make:seeder TenantUserSeeder

Run for a specific tenant:

$tenant->run(function () {
    \App\Models\User::factory()->count(10)->create();
});

👷 Step 8: Manually Switching Tenants (Advanced)

If you're running artisan commands or jobs, you may want to switch tenants manually:

use Stancl\Tenancy\Tenant;

$tenant = Tenant::find('acme');

$tenant->run(function () {
    // Code runs in tenant DB
    \App\Models\User::create(['name' => 'Test']);
});

🔔 Bonus: Using Events (Advanced Use)

Tenancy fires many events during tenant lifecycle.

Example: Seed user after tenant creation

Event::listen(TenantCreated::class, function ($event) {
    $event->tenant->run(function () {
        User::create([
            'name' => 'Admin',
            'email' => 'admin@demo.com',
        ]);
    });
});

🧰 Central Models (Non-Tenant Specific)

Sometimes you want shared models like Plan, Subscription, etc.

Use UsesTenantConnection trait for tenant models, and avoid it for central ones.

// Tenant Model
use Stancl\Tenancy\Database\Concerns\UsesTenantConnection;

// Central Model (normal Eloquent model)
class Plan extends Model {
  // uses central database
}

🌐 Real-World SaaS Flow (Example)

  • Main App (central) — auth, pricing, subscription

  • When a user signs up:

    • Create a tenant
    • Assign a subdomain
    • Seed admin user
  • Redirect to subdomain login

  • Each tenant has its own DB with user, projects, etc.


🌟 Final Thoughts

Tenancy for Laravel makes building multi-tenant SaaS platforms a breeze. It’s flexible, event-driven, and supports both single and multi-database setups.

You now have the tools to build:

  • CRM for multiple companies
  • School management systems
  • Team-based project tools
  • Ecommerce store with different vendors

💬 Have Questions?

Drop your questions or share your SaaS idea in the comments — happy to help!

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts