← All posts

Basic Laravel Multi-Tenancy

Let's learn the basic or simpliest form of multi-tenancy and third party packages

December 01, 20242 min read — multi-tenant · laravel · php

Basic Laravel Multi-tenancy

Tenancy often concerned as team, domain or something more complex but the most basic definition of multi-tenancy is that it divides your data based on the user, account, etc.,

From tenancy for laravel website

What is multi-tenancy?

Multi-tenancy is the ability to provide your service to multiple users (tenants) from a single hosted instance of the application. This is contrasted with deploying the application separately for each user.

You may find this talk insightful: https://multitenantlaravel.com/. Simply going through the slides will give you 80% of the value of the talk in under five minutes.

Note that if you just want to, say, scope todo tasks to the current user, there's no need to use a multi-tenancy package. Just use calls like auth()->user()->tasks(). This is the simplest form of multi-tenancy.

Repeating condition of filtering by user id

public function index()
{
	$books = Book::where('user_id', auth()->id())->get();
	return response()->json($books);
}

public function store(BookRequest $request)
{
	$book = Book::create($request->validated() + ['user_id' => auth()->id()]);
	return response()->json($book);
}

Bind user ID for every query automatically and when creating the model also. This may be repeated for other model and to prevent repetition we can extract this to a trait and apply it to the model.

Note: There are also other ways that this can be achieved.

class Book extends Model {

	protected static function boot()
	{
		parent::boot();

		self::creating(function($model) {
			$model->user_id = auth()->id()
		});

		self::addGlobalScope(function(Builder $builder) {
			$builder->where('user_id', auth()->id());
		})
	}

}

Move the boot method to a trait so that it can be applied directly to the models that will need it.

use Illuminate\Database\Eloquent\Builder;

trait FilterByUser {

	protected static function boot()
	{
		parent::boot();

		self::creating(function($model) {
			$model->user_id = auth()->id()
		});

		self::addGlobalScope(function(Builder $builder) {
			$builder->where('user_id', auth()->id());
		})
	}

}

Book Model will now look like this.

use App\Traits\FilterByUser;

class Book extends Model {
	use FilterByUser;

	protected $fillable = ['book', 'author', 'published_at'];
}

The concept of multi-tenancy enables a single application instance to serve multiple users (tenants) while isolating their data securely. However, for simple scenarios like scoping resources to individual users, implementing a full multi-tenancy package is unnecessary. Instead, you can manage resource filtering by leveraging traits to minimize code repetition.

For developers requiring robust multi-tenancy solutions in Laravel, Here are some recommended packages:

  1. Tenancy For Laravel
  2. Laravel Multi-tenancy