spatie/laravel-permission: database-backed roles and permissions for Laravel
Associate users with roles and permissions
At a glance
- What is it?
- The package stores roles and permissions in your database and registers every permission on Laravel's gate, so authorization checks run through the framework's own can() method. It fits Laravel applications that need admin-editable access control, and it is the wrong tool when your authorization rules are dynamic rather than role-shaped.
- Who is it for?
- Adopt spatie/laravel-permission if you run a Laravel application and want roles and permissions editable from the database rather than hardcoded in policies. Do not adopt it if your access rules depend on runtime state such as ownership or resource attributes, because those belong in Laravel policies, not in a role table.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 25 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Who needs database-backed roles instead of hardcoded gates
Laravel's gate and policy system assumes you can name an ability in code and attach logic to it. That works until someone in operations needs to create a new role, or until a customer asks for a permission set you did not anticipate. spatie/laravel-permission moves that decision into the database. The README describes the package as managing user permissions and roles in a database, and the usage examples are three lines long: give a permission directly to a user, assign a role, or attach a permission to a role. The audience is Laravel developers building applications with an admin interface, where the set of roles changes after deployment. If your application ships with exactly two roles and they never change, this package adds tables and cache invalidation for no reason.
Permissions are registered on Laravel's gate, so can() keeps working
The mechanism the README highlights is integration with Laravel's gate. Because every permission is registered there, a check reads as $user->can('edit articles'), the same call you would use for any other ability. That means existing middleware, Blade directives and policy code do not need a parallel API. The repository layout supports the rest of the picture: there is a config/ directory for the published configuration file, a database/ directory holding the migrations that create the permission tables, and src/ for the package code. Roles and permissions are rows, not constants, which is what makes them editable at runtime. The trade-off is that a database read now sits behind authorization. The package addresses this with caching, which is also why clearing the cache is a recurring operational task rather than a one-time install step.
Installing spatie/laravel-permission and granting a first permission
The README points to the documentation site for installation and upgrade guidance rather than reproducing the steps, so the authoritative sequence lives there. The package is distributed on Packagist as spatie/laravel-permission, which is the name you require with Composer. The README's own testing instructions show the Composer script convention the project uses:
composer testAfter installation and migration, the README gives these usage examples. They are the first real thing you do with the package: attach a permission to a user, or go through a role.
// Adding permissions to a user
$user->givePermissionTo('edit articles');
// Adding permissions via a role
$user->assignRole('writer');
$role->givePermissionTo('edit articles');The check itself uses Laravel's default can function, which is the point of the gate integration:
$user->can('edit articles');What you should see is a boolean from can() that reflects the rows you just created. If it returns false immediately after assigning a permission, the usual cause is a stale permission cache, and the documentation covers cache clearing for exactly that reason.
The permission cache is the failure mode you will actually hit
Caching is what makes database-backed authorization viable on every request, and it is also the package's most common source of confusion. When permissions change through a seeder, a direct database edit, or a deployment that runs migrations, the cached set can lag behind the rows. The symptom is a user who should have access being denied, or the reverse. The documentation addresses cache clearing, and the related search terms people use around this package include cache clearing and permission denied, which suggests the problem is widespread enough to be searched for by name. Treat cache invalidation as part of your deployment procedure, not as an emergency fix. The second limitation is conceptual: this package models access as role and permission assignments. Rules like "a user may edit a post only if they authored it" are not role-shaped, and forcing them into permissions produces a combinatorial set of permission names. Those rules belong in Laravel policies, with this package handling the coarse layer.
Bouncer and the alternatives take a different angle on authorization
The README itself lists alternatives and links to a Laravel News article comparing this package to Joseph Silber's Bouncer, which the README calls an excellent package. The difference in approach is where the rules live. spatie/laravel-permission keeps roles and permissions as database rows that administrators can edit, which is why it needs tables, migrations and a cache. Bouncer leans toward abilities defined against models, closer to Laravel's policy style, which suits teams that want authorization logic expressed in code and versioned with it. The README also notes santigarcor/laratrust for team support, meaning multi-tenant role scoping is not a first-class feature here, and mentions ultraware/roles as taking a slightly different approach, plus zizaco/entrust for wildcard pattern matching. If wildcard permission names are central to your design, that last point is worth investigating before you commit to this package.
Maintenance, version churn and the MIT licence
The last push to the default branch was on 2026-09-04, and the most recent releases listed are 8.3.0 on 2026-07-03, 8.2.0 earlier the same day, and 8.1.0 on 2026-06-27. The repository is not archived. That release cadence matters for planning: the package is on a major version 8 line, and the README directs readers to the documentation for upgrade guidance rather than describing upgrades inline. Budget time for reading that guide whenever you bump Laravel, because a major version of this package and a major version of the framework tend to move together. The licence is MIT, stated in the README and present as LICENSE.md at the repository root. MIT is permissive and imposes no copyleft obligation on your application, but the README also mentions postcardware: the authors ask for a postcard if the package reaches production. That is a request, not a licence term, and it does not change what MIT permits. For legal questions about your own distribution, consult a lawyer rather than the README.
Editorial conclusion
Adopt spatie/laravel-permission if you run a Laravel application and want roles and permissions editable from the database rather than hardcoded in policies. Do not adopt it if your access rules depend on runtime state such as ownership or resource attributes, because those belong in Laravel policies, not in a role table. Before committing, verify that your Laravel version is covered by the current release line and read the upgrade guide in the documentation, since the package has gone through several major versions and the upgrade steps are the part most likely to bite during a framework bump.
Frequently asked questions
What is the difference between a role and a permission in spatie/laravel-permission?
A permission is a single named ability such as "edit articles", while a role is a named container you attach permissions to and then assign to users. The README shows both paths: you can give a permission straight to a user, or assign a role and give the permission to that role.
How do Spatie roles and permissions work in Laravel?
Roles and permissions are stored in database tables created by the package's migrations, and every permission is registered on Laravel's gate. That registration is why a check reads as $user->can('edit articles') using Laravel's default can function.
How do I install spatie/laravel-permission?
The README does not reproduce the install steps; it directs you to the documentation site for installation and upgrade guidance. The package is published on Packagist as spatie/laravel-permission, so Composer is the installation path.
What is spatie/laravel-permission?
It is a Laravel package that lets you manage user permissions and roles in a database, as the README's opening description puts it. Once installed, you assign permissions or roles to users and check them through Laravel's gate.
What is a good alternative to spatie/laravel-permission?
The README points to Bouncer by Joseph Silber, which it calls an excellent package, and to a Laravel News article comparing the two. It also lists santigarcor/laratrust for team support, ultraware/roles for a slightly different feature approach, and zizaco/entrust for wildcard pattern matching.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spatie-laravel-permission)