Most multi-tenancy bugs I've worried about in Laravel apps aren't dramatic. Nobody hacks anything. A query runs without a tenant filter, returns a few extra rows, and those rows end up in a CSV export, a dashboard widget, or an email that goes to the wrong customer.
When I wrote laravel-tenancy , a single-database tenancy package for Laravel, I made one decision early and built everything else around it: if the package isn't sure which tenant a query belongs to, it refuses to run the query. This post explains that choice, what it costs, and how it plays out in practice.
The usual setup, and where it leaks
Single-database tenancy (sometimes called shared-schema or row-level tenancy) is simple on paper. Every tenant-owned table has a team_id column. You add a global scope that appends where team_id = ? to every query. Done.
The weak spot is what happens when there's no current tenant.…