Multi-tenancy in Laravel helps serve various clients using a single Laravel application. Through multi-tenancy implementation, we can maintain separate and secure databases for each tenant.
Here are the three key strategies to implement multi-tenancy in Laravel:
Single Database – Tenant ID Column (Simple & Lightweight)
In this method, all tenants share the same database and tables, but each record has a tenant_id column. Laravel uses this to scope data to the correct tenant.
Example:
Suppose you have a projects table. Add a tenant_id column:
PHP:
Schema::create('projects', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('tenant_id'); $table->string('name'); $table->timestamps();
});
Apply Global Scope:
Create a scope to automatically filter data for the logged-in tenant:
PHP:
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class TenantScope implements Scope
{ public function apply(Builder $builder, Model $model) { if (auth()->check()) { $builder->where('tenant_id', auth()->user()->tenant_id); } }
}
Apply this in your model (e.g. Project.php):
PHP:
protected static function booted()
{ static::addGlobalScope(new TenantScope);
}
Bonus Tip:
Always assign the tenant_id when creating records:
Project::create([ 'name' => 'Tenant Project', 'tenant_id' => auth()->user()->tenant_id,
]);
Multiple Databases – One Database per Tenant (Isolated & Scalable)
Each tenant gets a separate database, and Laravel switches between them dynamically.
Example:
Tenants:
- tenant1: tenant1_db
- tenant2: tenant2_db
Set tenant database at runtime:
PHP:
// Middleware or Service
public function switchTenantDatabase($tenantDatabaseName)
{ config([ 'database.connections.tenant.database' => $tenantDatabaseName, ]); DB::purge('tenant'); // Clear old connection DB::reconnect('tenant'); // Reconnect to new DB
}
Use a special tenant connection in config/database.php:
PHP:
'tenant' => [ 'driver' => 'mysql', 'host' => env('DB_HOST'), 'database' => '', // will be set dynamically 'username' => env('DB_USERNAME'), 'password' => env('DB_PASSWORD'), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
],
Benefits:
- True isolation between tenants
- Easier backup & per-tenant scaling
- But more complex to maintain and deploy
Multiple Schemas – (PostgreSQL Only)
A personalized schema is assigned to each tenant within a single PostgreSQL database. Laravel does not support schema switching out of the box, but it’s possible with packages or custom logic.
Use a Package: stancl/tenancy (Recommended for Complex Apps)
For production-level applications, use the stancl/tenancy package. It supports:
- Subdomains or custom domains per tenant
- Automatic DB provisioning
- Centralized vs tenant-specific logic
- Works with both database and filesystem isolation
Example Using stancl/tenancy
Bash:
composer require stancl/tenancy
php artisan tenancy:install
php artisan migrate
Tenant creation:
PHP:
Tenant::create([ 'id' => 'tenant1', 'data' => ['name' => 'Tenant One']
]);
Then you can run tenant-specific migrations:
Bash:
php artisan tenants:migrate
Key Considerations
Area | Strategy |
Data isolation | Use separate databases or schemas |
Automation | Automate tenant setup & migration |
Access control | Use policies to restrict tenant data |
Central logic | Share code, separate the data |
Backups | Plan for tenant-wise data recovery |
Scaling | Choose architecture based on load |
Summary
Approach | Pros | Cons |
Single DB (tenant_id) | Simple, fast setup | Not fully isolated |
Multiple DBs | Strong isolation, scalable | More complex config |
Multiple Schemas | Isolated (PostgreSQL only) | Laravel doesn’t support natively |
Package (stancl) | Powerful, feature-rich | Requires learning curve |
If you are still confused about the approach you should take, hire dedicated Laravel developers from a reputed and experienced development company, to guide your Laravel multi-tenancy implementation requirements.