PHPackages                             scabarcas/laravel-permissions-redis - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. scabarcas/laravel-permissions-redis

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

scabarcas/laravel-permissions-redis
===================================

A Redis-powered roles and permissions package for Laravel designed to eliminate repetitive database queries and deliver high-performance authorization.

v4.0.0(1mo ago)37186↓87%2MITPHPPHP ^8.3CI passing

Since Mar 19Pushed 3w agoCompare

[ Source](https://github.com/scabarcas17/laravel-permissions-redis)[ Packagist](https://packagist.org/packages/scabarcas/laravel-permissions-redis)[ GitHub Sponsors](https://github.com/scabarcas17)[ RSS](/packages/scabarcas-laravel-permissions-redis/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (23)Versions (10)Used By (0)

 [ ![Laravel Permissions Redis, high-performance Redis-backed roles and permissions for Laravel](.github/assets/hero.png) ](https://github.com/scabarcas17/laravel-permissions-redis)

Laravel Permissions Redis
=========================

[](#laravel-permissions-redis)

A high-performance, Redis-backed roles and permissions package for Laravel. Eliminates repetitive database queries by caching all authorization data in Redis with automatic invalidation.

Inspired by [spatie/laravel-permission](https://github.com/spatie/laravel-permission), the de facto standard for roles and permissions in Laravel. This package adopts its familiar API (`hasRole`, `hasPermissionTo`, `assignRole`, Blade directives, middleware) while replacing the database-per-request approach with a Redis-first architecture for applications where authorization throughput is critical.

[![CI](https://github.com/scabarcas17/laravel-permissions-redis/actions/workflows/ci.yml/badge.svg)](https://github.com/scabarcas17/laravel-permissions-redis/actions/workflows/ci.yml)[![codecov](https://camo.githubusercontent.com/d2ca70413ee006b841915103db6a90fff696356d5d4367b99fedad76adc1f00b/68747470733a2f2f636f6465636f762e696f2f67682f73636162617263617331372f6c61726176656c2d7065726d697373696f6e732d72656469732f67726170682f62616467652e737667)](https://codecov.io/gh/scabarcas17/laravel-permissions-redis)[![Latest Version on Packagist](https://camo.githubusercontent.com/356e3062d323f9e7e46b5e91037ca7a23d883855aefdc7b86c5d8e77ca31c906/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7363616261726361732f6c61726176656c2d7065726d697373696f6e732d72656469732e737667)](https://packagist.org/packages/scabarcas/laravel-permissions-redis)[![Total Downloads](https://camo.githubusercontent.com/d7e0f30d91e699218fcba15e4b9caf3a324b2b10b4b5824ad6cf8bea974a6555/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7363616261726361732f6c61726176656c2d7065726d697373696f6e732d72656469732e737667)](https://packagist.org/packages/scabarcas/laravel-permissions-redis)[![PHP 8.3+](https://camo.githubusercontent.com/89899a77bdce65fc4c3d3423dfacff9c6461066a0b5354dc18d7721c23ba596e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332532422d626c75652e737667)](https://php.net)[![Laravel 11|12|13](https://camo.githubusercontent.com/977ed8891f0c3f376e098db6a13fd1aa413d5d0c4e380d9a550a475e52696470/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3131253230253743253230313225323025374325323031332d7265642e737667)](https://laravel.com)[![PHPStan Level Max](https://camo.githubusercontent.com/b6d441ad4fe8332cb16c72aa27f22cc685181dfd74ae34964afc92c6c1146b3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e737667)](https://phpstan.org/)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

---

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Architecture](#architecture)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage Guide](#usage-guide)
    - [Setting Up the User Model](#setting-up-the-user-model)
    - [Creating Roles and Permissions](#creating-roles-and-permissions)
    - [Assigning Roles and Permissions](#assigning-roles-and-permissions)
    - [Checking Roles and Permissions](#checking-roles-and-permissions)
    - [Middleware](#middleware)
    - [Blade Directives](#blade-directives)
    - [Gate Integration](#gate-integration)
    - [Wildcard Permissions](#wildcard-permissions)
    - [Super Admin](#super-admin)
    - [Cache Management](#cache-management)
- [UUID / ULID Support](#uuid--ulid-support)
- [Laravel Octane](#laravel-octane)
- [Multi-Tenancy](#multi-tenancy)
- [Integrations](#integrations)
- [Conventions](#conventions)
- [API Reference](#api-reference)
- [Testing](#testing)
- [Comparison with spatie/laravel-permission](#comparison-with-spatielaravel-permission)
    - [Feature Comparison](#feature-comparison)
    - [Performance Benchmark](#performance-benchmark)
    - [When to Use This Package](#when-to-use-this-package)
- [Migrating from Spatie](#migrating-from-spatie)
- [Troubleshooting](#troubleshooting)
- [License](#license)

---

Requirements
------------

[](#requirements)

### Runtime

[](#runtime)

DependencyVersionPurpose**PHP**`^8.3`Typed properties, enums, fibers, `readonly` classes**Laravel Framework**`^11.0 | ^12.0 | ^13.0`Host application**Redis extension**`phpredis` or `predis`Redis connectivity### PHP Extensions

[](#php-extensions)

ExtensionRequiredNotes`redis` (phpredis)Yes\*Recommended for production. Install via `pecl install redis``json`YesBundled with PHP 8.3+`mbstring`YesRequired by Laravel> \* You can use `predis/predis` as a userland alternative if `phpredis` is not available. Configure `'client' => 'predis'` in `config/database.php` under the Redis section.

### Laravel Components Used

[](#laravel-components-used)

PackageVersionRole in the package`illuminate/support``^11.0 | ^12.0 | ^13.0`Service provider, collections, helpers`illuminate/database``^11.0 | ^12.0 | ^13.0`Eloquent models, migrations, query builder`illuminate/redis``^11.0 | ^12.0 | ^13.0`Redis connection manager`illuminate/events``^11.0 | ^12.0 | ^13.0`Event dispatching and cache invalidation`illuminate/auth``^11.0 | ^12.0 | ^13.0`Gate integration, login event listener### Development Dependencies

[](#development-dependencies)

PackageVersionPurpose`pestphp/pest``^4.4`Testing framework`phpstan/phpstan``^2.1`Static analysis`larastan/larastan``^3`Laravel-specific static analysis rules`laravel/pint``^1.29`Code style formatting (PSR-12)`orchestra/testbench``^10.11 | ^11.0`Laravel package testing harness### Infrastructure

[](#infrastructure)

ServiceVersionNotes**Redis Server**`6.0+`Required. Uses SET data structures and MULTI/EXEC transactions**Database**MySQL 8.0+ / PostgreSQL 13+ / SQLite 3.35+Any database supported by Laravel migrations---

Architecture
------------

[](#architecture)

> **Note:** The diagrams below use [Mermaid](https://mermaid.js.org/). If they appear as code blocks, [view them rendered on GitHub](https://github.com/scabarcas17/laravel-permissions-redis#architecture).

### System Context

[](#system-context)

 ```
flowchart LR
    User["👤 Application User"]

    subgraph system [" "]
        App["🟩 Laravel Application\nRoles & permissions\nfor authorization"]
    end

    Redis[("🔴 Redis\nCached permissions\nand roles as SETs")]
    DB[("🟦 Database\nSource of truth:\npermissions, roles,\nassignments")]

    User -- "HTTP requests" --> App
    App -- "Read: SISMEMBER, SMEMBERS\nWrite: warm / evict" --> Redis
    App -- "Read/Write:\nrole & permission\ndefinitions" --> DB
```

      Loading ### Container Diagram

[](#container-diagram)

 ```
flowchart TB
    User["👤 Application User"]

    subgraph laravel ["Laravel Application"]
        direction TB

        subgraph entry ["Entry Points"]
            MW["🛡️ Middleware\npermission · role\nrole_or_permission"]
            BL["🖼️ Blade Directives\n@role · @permission\n@hasanyrole · ..."]
        end

        Trait["📦 HasRedisPermissions\nUser Model Trait\nassign · check · sync"]

        subgraph core ["Resolution & Cache"]
            direction LR
            Resolver["⚙️ PermissionResolver\nIn-memory cache\nWildcard matching"]
            Repo["🔌 RedisPermissionRepository\nSISMEMBER · SMEMBERS\nMULTI/EXEC atomicity"]
        end

        subgraph sync ["Sync & Events"]
            direction LR
            Manager["♻️ AuthorizationCacheManager\nwarmAll · warmUser\nevictUser · evictRole"]
            Events["📡 CacheInvalidator\nRolesAssigned\nPermissionsSynced\nRoleDeleted"]
        end
    end

    Redis[("🔴 Redis\nSETs with TTL")]
    DB[("🟦 Database\n5 tables")]

    User -- "HTTP Request" --> MW
    User -- "Views" --> BL
    MW --> Trait
    BL --> Trait
    Trait --> Resolver
    Resolver --> Repo
    Repo -- "Read/Write" --> Redis
    Events --> Manager
    Manager -- "Queries" --> DB
    Manager --> Repo
```

      Loading ### Resolution Flow

[](#resolution-flow)

 ```
flowchart TD
    A["hasPermissionTo('posts.edit')"] --> B{In-memory\ncache?}
    B -- "Hit" --> C["✅ Return cached result"]
    B -- "Miss" --> D{"Redis\nSISMEMBER?"}
    D -- "Hit" --> E["✅ Cache in memory\nand return"]
    D -- "Miss" --> F{"User cache\nexists in Redis?"}
    F -- "Yes" --> K{"Wildcard\nenabled?"}
    F -- "No (cold start)" --> H["AuthorizationCacheManager\n::warmUser()"]
    H --> I["Query DB:\ndirect perms + role perms"]
    I --> J["Write merged SETs\nto Redis"]
    J --> D

    K -- "No" --> L["❌ Permission denied"]
    K -- "Yes" --> M["fnmatch() scan\nall user perms"]
    M -- "Match" --> N["✅ Return true"]
    M -- "No match" --> L

```

      Loading ### Cache Invalidation Flow

[](#cache-invalidation-flow)

 ```
flowchart TD
    A["Database Change"] --> B{"Event Type"}

    B -- "RolesAssigned" --> D["Rewarm user cache\n+ reindex role to users"]
    B -- "PermissionsSynced" --> E["Rewarm role\n+ all users with that role"]
    B -- "RoleDeleted" --> F["Evict role cache\n+ rewarm affected users"]
    B -- "UserDeleted" --> G["Evict user cache\nfrom Redis"]
    B -- "Login" --> H["Warm user cache\non authentication"]

    D --> I["✅ Redis Updated"]
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J["PermissionResolver\nin-memory cache flushed"]
```

      Loading ### Redis Key Structure

[](#redis-key-structure)

```
auth:user:{userId}:permissions   -> SET of permission names
auth:user:{userId}:roles         -> SET of role names
auth:role:{roleId}:permissions   -> SET of permission names
auth:role:{roleId}:users         -> SET of user IDs

```

---

Installation
------------

[](#installation)

### Requirements

[](#requirements-1)

- PHP 8.3+
- Laravel 11, 12, or 13
- Redis extension (`phpredis` or `predis`)

### Step 1: Install via Composer

[](#step-1-install-via-composer)

```
composer require scabarcas/laravel-permissions-redis
```

The service provider is auto-discovered. No manual registration needed.

### Step 2: Publish Assets

[](#step-2-publish-assets)

Publish config and migrations together:

```
php artisan vendor:publish --provider="Scabarcas\LaravelPermissionsRedis\PermissionsRedisServiceProvider"
```

Or publish individually by tag:

```
# Config only
php artisan vendor:publish --tag=permissions-redis-config

# Migrations only
php artisan vendor:publish --tag=permissions-redis-migrations
```

### Step 3: Run Migrations

[](#step-3-run-migrations)

```
php artisan migrate
```

Creates 5 tables: `permissions`, `roles`, `model_has_permissions`, `model_has_roles`, `role_has_permissions`.

### Step 4: Configure Redis

[](#step-4-configure-redis)

Ensure your `config/database.php` has a working Redis connection. The package uses `'default'` by default:

```
// .env
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null
```

### Step 5: Warm the Cache

[](#step-5-warm-the-cache)

```
php artisan permissions-redis:warm
```

This loads all existing permissions and roles into Redis. Run this after initial setup or after direct database modifications.

---

Configuration
-------------

[](#configuration)

All options live in `config/permissions-redis.php`:

OptionEnv VariableDefaultDescription`redis_connection``PERMISSIONS_REDIS_CONNECTION``'default'`Redis connection from `config/database.php``prefix``PERMISSIONS_REDIS_PREFIX``'auth:'`Prefix for all Redis keys`ttl``PERMISSIONS_REDIS_TTL``86400`Cache TTL in seconds (24h)`user_model``PERMISSIONS_REDIS_USER_MODEL``App\Models\User`Your User model (accepts a string **or array** of FQCNs)`log_channel``PERMISSIONS_REDIS_LOG_CHANNEL``null`Log channel (`null` = default)`register_gate`*(none)*`true`Enable `Gate::before` integration`register_middleware`*(none)*`true`Register middleware aliases`warm_on_login`*(none)*`true`Auto-warm cache on user login`super_admin_role``PERMISSIONS_REDIS_SUPER_ADMIN_ROLE``null`Role that bypasses all checks`wildcard_permissions``PERMISSIONS_REDIS_WILDCARD``false`Enable `fnmatch()` wildcard patterns`register_blade_directives`*(none)*`true`Register Blade directives`resolver_cache_limit``PERMISSIONS_REDIS_RESOLVER_LIMIT``1000`Max users held in the in-memory resolver cache before LRU eviction`resolver_warm_cooldown``PERMISSIONS_REDIS_WARM_COOLDOWN``1.0`Seconds before a failed cache-miss warm is retried for the same user`queue.connection``PERMISSIONS_REDIS_QUEUE_CONNECTION``null`Queue connection used by `WarmUserCacheJob` (`null` = default)`queue.name``PERMISSIONS_REDIS_QUEUE_NAME``'default'`Queue name for warming jobs`seed`*(none)**(see config)*Roles and permissions to seed via CLI`tables`*(none)**(see config)*Custom table names---

Usage Guide
-----------

[](#usage-guide)

### Setting Up the User Model

[](#setting-up-the-user-model)

Add the `HasRedisPermissions` trait to your User model:

```
