---
title: Creating a Multi-Tenant Application with Laravel and Neon
subtitle: Learn how to build a scalable multi-tenant application using Laravel and Neon's powerful database features
author: bobbyiliev
enableTableOfContents: true
createdAt: '2024-06-30T00:00:00.000Z'
updatedOn: '2024-06-30T00:00:00.000Z'
---
Multi-tenancy is a software architecture where a single instance of an application serves multiple tenants or clients.
Each tenant's data is isolated and remains invisible to other tenants. This approach is commonly used in Software as a Service (SaaS) applications. In this tutorial, we'll build the foundation for a multi-tenant SaaS application using Laravel and Neon.
By the end of this tutorial, you'll have a fully functional multi-tenant SaaS application where tenants can manage their own books, users, and settings, all while maintaining data isolation between tenants.
## Prerequisites
Before we start, make sure you have the following:
- PHP 8.1 or higher installed on your system
- [Composer](https://getcomposer.org/) for managing PHP dependencies
- [Node.js](https://nodejs.org/) and npm for managing front-end assets
- A [Neon](https://console.neon.tech/signup) account for database hosting
- Basic knowledge of Laravel and Livewire
## Setting up the Project
Let's start by creating a new Laravel project and setting up the necessary components.
### Creating a New Laravel Project
Open your terminal and run the following command to create a new Laravel project:
```bash
composer create-project laravel/laravel laravel-multi-tenant-saas
cd laravel-multi-tenant-saas
```
### Installing Required Packages
For our multi-tenant SaaS application, we'll use the following package:
- `stancl/tenancy`: A flexible multi-tenancy package for Laravel
- Laravel Breeze: A minimal authentication starter kit for Laravel
Start by installing the `stancl/tenancy` package:
```bash
composer require stancl/tenancy
```
After installing the package, let's set up the tenancy:
```bash
php artisan tenancy:install
```
Register the `TenancyServiceProvider` in the `bootstrap/providers.php` file:
```php
return [
// ...
App\Providers\TenancyServiceProvider::class,
],
```
Let's install Laravel Breeze with the Blade views:
```bash
composer require laravel/breeze --dev
php artisan breeze:install blade
```
Next, install the required NPM packages:
```bash
npm install
npm run dev
```
### Setting up the Database
Update your `.env` file with your Neon database credentials:
```env
DB_CONNECTION=pgsql
DB_HOST=your-neon-hostname.neon.tech
DB_PORT=5432
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password
```
After updating the `.env` file, run the database migrations:
```bash
php artisan migrate
```
## Implementing Multi-Tenancy
Now that we have our basic setup, let's implement multi-tenancy in our application.
### Creating the Tenant Model
Create a `Tenant` model:
```bash
php artisan make:model Tenant
```
Update the `app/Models/Tenant.php` file:
```php
\App\Models\Tenant::class,
```
Also, update the central domains configuration:
```php
'central_domains' => [
'laravel-multi-tenant-saas.test',
'localhost',
'example.com',
],
```
Replace the default central domains with your own domain names.
This is an important part as this is how the tenancy package will determine which domain belongs to which tenant and load the tenant-specific data accordingly.
Feel free to review the other configuration options in the `config/tenancy.php` file to customize the tenancy behavior based on your requirements.
### Creating Tenant Migrations
The tenancy package has built-in event listeners that automatically run tenant-specific migrations when a tenant is created. For this we need to make sure that all of the tenant-specific migrations are in the `database/migrations/tenant` directory.
As each tenant will have its own database, the migrations in the tenant directory will be used to create tenant-specific tables in the tenant's database.
Start by copying the default User migration to the `database/migrations/tenant` directory:
```bash
cp database/migrations/0001_01_01_000000_create_users_table.php database/migrations/tenant
```
This will be the base migration for tenant-specific tables.
### Implementing Tenant Routes
The tenancy package provides middleware to handle tenant-specific routes. This allows you to define routes that are accessible only to tenants and not to central domains.
Start by creating a new file `routes/tenant.php` for tenant-specific routes with the following content:
```php
group(function () {
Route::get('/', function () {
return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
});
// Here you can add more tenant-specific routes
});
```
These routes will be loaded by the `TenantRouteServiceProvider` and will be accessible only to tenants. The `InitializeTenancyByDomain` middleware will set the current tenant based on the domain, and the `PreventAccessFromCentralDomains` middleware will prevent access from central domains.
For more information on how to customize the tenancy routes, refer to the [stancl/tenancy documentation](https://tenancyforlaravel.com/docs/v3/routes).
### Implementing Tenant Creation
Create a controller for tenant registration, this would usually be done by the admin users of the application:
```bash
php artisan make:controller TenantController
```
Update the `app/Http/Controllers/TenantController.php` controller and implement the tenant registration process:
```php
validate([
'domain' => 'required|string|max:255|unique:domains,domain',
]);
$tenant = Tenant::create();
$tenant->domains()->create(['domain' => $request->domain]);
return redirect()->route('tenant.registered', $request->domain);
}
public function registered($domain)
{
return view('tenant.registered', compact('domain'));
}
}
```
This controller handles tenant registration, creates a new tenant in the database, and sets up the tenant's domain. The `TenancyServiceProvider` will automatically map the tenancy events to the listener, which will create the tenant's database and run the tenant-specific migrations inside the `database/migrations/tenant` directory for the new tenant.
In a nutshell, the controller has three methods:
- `showRegistrationForm()`: Displays the tenant registration form
- `register()`: Registers a new tenant, which creates a new tenant record and domain
- `registered()`: Displays a success message after registration
This controller will be used to manage tenant registration in our application. Allowing new tenants to register and create their own subdomain and database for their account.
Add routes for tenant registration in `routes/web.php`:
```php
use App\Http\Controllers\TenantController;
Route::get('/register', [TenantController::class, 'showRegistrationForm'])->name('tenant.register');
Route::post('/register', [TenantController::class, 'register']);
Route::get('/registered/{domain}', [TenantController::class, 'registered'])->name('tenant.registered');
```
Create the corresponding views for tenant registration starting by creating the `resources/views/tenant/register.blade.php` file:
```html
{{ __('Dashboard') }}