Implementing Multi-Tenancy with Laravel Jetstream Teams
Learn how to enable and configure Laravel Jetstream Teams to implement multi-tenancy, including installation flags, configuration for invitations, and verification steps.
28 Sept 2025, 05:24 UTC

The Challenge of Team-Based Authorization
Building a multi-tenant application usually requires a complex architecture of foreign keys, middleware to track the active organization, and custom UI for switching contexts. For developers using Laravel, the primary hurdle is not just the database schema, but the state management required to ensure a user is acting on behalf of the correct team across different requests.
The takeaway: Laravel Jetstream provides a built-in Teams feature that handles the schema, the current-team session state, and the management UI, allowing you to focus on team-specific logic rather than the scaffolding of the multi-tenancy engine.
Prerequisites
- A functional Laravel application (version 8.x or higher).
- A configured database connection.
- Node.js and NPM installed for frontend asset compilation.
- A decided frontend stack: either Livewire (Blade-based) or Inertia.js (Vue-based).
Enabling the Teams Feature
Jetstream Teams must be enabled during the installation process to ensure the necessary migrations and views are published. If you have already installed Jetstream without teams, you will need to manually add the feature to the configuration and run the migrations, but the installer flag is the supported path for new setups.
Run the following commands in your terminal from the project root. Replace livewire with inertia if using the Vue stack.
# Step 1: Install the Jetstream package via Composer
composer require laravel/jetstream
# Step 2: Run the installer with the --teams flag
# Required permissions: Write access to the project directory
php artisan jetstream:install livewire --teams
# Step 3: Apply the database migrations
php artisan migrate
# Step 4: Compile the frontend assets
npm install && npm run build
Configuring Team Behavior
Once installed, the team logic is controlled via config/jetstream.php. Locate the features array to toggle specific functionalities. The Features::teams constant enables the core engine, but you can refine the behavior within the configuration file.
Example configuration for a strict team environment where invitations are required:
// config/jetstream.php
'features' => [
Features::teams => [
'broadcasts' => true,
'invitations' => true, // Enables the team_invitations table and invite UI
'deletions' => true, // Allows team owners to delete the team
],
// ... other features
],
Verification and Testing
To ensure the implementation is active and routing is correct, perform the following checks.
1. Route Inspection
Run the route list command to verify that the team management endpoints are registered. Run this on your local development server:
php artisan route:list --path=teams
Expected Result: You should see routes such as teams.index, teams.store, and teams.show.
2. Database State Check
Create a team through the application dashboard. Then, use a database client or php artisan tinker to verify the records:
- Check the
teamstable for the new team record. - Check the
team_usertable to ensure your user ID is linked to the team ID. - If invitations are enabled, invite a user and verify a record exists in
team_invitations.
3. Authorization Guard Test
Attempt to access a team-specific URL (e.g., /teams/{id}) while logged in as a user who is not a member of that team. The application should return a 403 Forbidden response, confirming that the Jetstream team policies are active.
Limitations and Considerations
- Session State: Jetstream stores the
current_team_idin the session. If you implement custom API endpoints, you must manually handle the team context via thecurrentTeam()method on the User model. - Custom Guards: If your app uses custom authentication guards, you may need to override the
Jetstream::user()resolution to ensure the team context is correctly retrieved.
Rollback Procedure
If you need to disable the Teams feature, follow these steps to avoid orphaned data or routing errors:
- Remove
Features::teamsfrom thefeaturesarray inconfig/jetstream.php. - Clear the configuration cache:
php artisan config:clear. - Caution: Do not run a general
migrate:rollbackin production. Instead, identify the specific migrations that created theteams,team_user, andteam_invitationstables and drop them manually or via a targeted migration rollback if you have a recent backup. - Rebuild assets using
npm run buildto remove team-related UI components from the compiled bundle.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.