Make your Laravel application multi-tenant without changing a line of code
Samuel Štancl • October 6, 2019
A package of mine, stancl/tenancy, lets you add multi-tenancy to Laravel applications without having to change how you write your app.
It automatically switches the database connection, cache, filesystem, Redis and queue in the background, letting you write code that doesn't need to be aware of any specifics related to multi-tenancy.
You can read more about the package here: tenancy.samuelstancl.me.
To install the package, first you need to require it via composer:
composer require stancl/tenancy
Then, you can use the install command to publish all assets and make the necessary changes to your http kernel.
php artisan tenancy:install
If you're not running this in a fresh Laravel application, it's wise to see what the install command does. It could cause issues if your application structure is too custom. Installing the package manually shouldn't take more than a minute.
For this package, routes are what distinguishes the tenant part of the application from the central part. Rather than applying model traits and similar things, just decide what routes belong to the tenant part of the app.
Routes for your tenant part of the application must be located in
routes/web.php file should be used for "central" routes — landing page, sign up page, etc.
Note that routes in these two files can't be conflicting, so it may be useful to prefix all tenant routes with
app/, for example.
By default, when the application is visited, the package attempts to find a tenant who owns the domain in the request.
If the current domain doesn't belong to any tenant, an exception is thrown.
Add the domains for the central part of the application to the
// config/tenancy.php 'exempt_domains' => [ 'yourapp.com', ],
Move the migrations that should interact with tenant databases to
Finally, creating tenants. The last step to have a working multi-tenant app.
To create a tenant, you may use the following method:
use Stancl\Tenancy\Tenant; Tenant::new()->withDomains([ 'client1.yourapp.com', 'client1.com', ])->save();
To test your application locally, you may use domains under the
.localhost top level domain. All of those domains are routed to
Testing it out
Let's create two tenants: one on the
foo.localhost domain and one on the
You can run these methods in
php artisan tinker for development.
use Stancl\Tenancy\Tenant; $tenant1 = Tenant::new()->withDomains('foo.localhost')->save(); $tenant2 = Tenant::new()->withDomains('bar.localhost')->save();
Make sure your application is running on localhost and your web server accepts all hostnames (
artisan serve does).
It's likely you'll get a Table not found error when you visit the page — if it interacts with the database. To run tenant migrations, use the following artisan command:
php artisan tenants:migrate
And that's all there is to implementing multi-tenancy with stancl/tenancy.
Of course, in real world applications you need more things:
- storing additional information about the tenants, such as their subscription plan
- setting application config to tenant-specific values
- integrating with other packages, like Horizon and Telescope
- using custom database connections for specific tenants, to allow for on-premise database hosting
- testing your multi-tenant application
All of this, and much more, is covered in the package's documentation.
Thank you for reading this and I wish you success with your Software-as-a-Service.