Performance and monitoring
Persistent Redis for queues, sessions and Horizon
Redis Cache is a cache: it starts empty every time it restarts and evicts keys when it fills up. It is for storing what the application can calculate again, not a queue of pending jobs or a user's session. That is what persistent Redis is for: an instance of your own, in your account, that stores its data on disk and does not discard it when it fills up.
It is Valkey 8, compatible with Redis: the same commands and the same clients, such as PhpRedis, work. It is available on the Avanza, Max and Elastic plans.
Redis Cache or persistent Redis
| Redis Cache | Persistent Redis |
|---|---|
| On all plans | On Avanza, Max and Elastic |
| For caching | For queues, sessions and Horizon |
| 16 to 200 MB, depending on the plan | 64 to 512 MB, your choice |
| Starts empty after a restart | Keeps its data after a restart |
| Evicts keys when full | Rejects writes when full |
| Not included in backups | Included in the daily backups |
Redis Cache connects through /tmp/redis.sock; persistent Redis through /home/USUARIO/.hostsuar/redis/redis.sock, with your cPanel username instead of USUARIO. Redis Cache's memory depends on the plan; you choose the persistent one's, up to 128 MB on Avanza, 256 MB on Max and 512 MB on Elastic.
You can use both at once: the cache in Redis Cache and the queues and sessions in persistent Redis. We explain how further down.
In both cases the port is 0: they connect through a socket, with no network access. The application has to run on the hosting itself.
Enable it
- In the client area, open Hosting, go into your service and open Package manager.
- On the Persistent Redis card, click Enable.
- Check the memory, the persistence and what to do when it fills up. The default values work for queues, sessions and Horizon.
- Confirm and wait until the panel shows it running.
Persistent Redis takes up one of your plan's persistent processes and also appears in Tools > Processes. Each account has one; if all the processes in your plan are already in use, delete one before enabling it.
It runs as your account's user and within its resources. Only that user can open the socket, so it does not need a password.
Settings
Memory. 64 MB by default, with a maximum of 128 MB on Avanza, 256 MB on Max and 512 MB on Elastic. Queues and sessions take up little space: 64 MB is enough for most applications. With Horizon, memory grows with the metrics and recent jobs it keeps; you adjust them in trim, inside config/horizon.php.
Persistence.
- Every second (default): writes each change to a log file (AOF) and flushes it to disk every second. If there is an outage, you lose at most the last second. This is what queues and sessions need.
- No persistence: everything lives in memory and a restart leaves it empty. Use it only if you store data you can regenerate.
What it stores on disk is in ~/.hostsuar/redis/datos and counts towards your plan's disk space, even with Redis stopped. The Package manager card shows how much it takes up, next to the memory. Queues and sessions usually stay at a few megabytes: the log file compacts itself when it grows.
When full.
- Don't lose data (default): when it reaches the limit, it rejects new writes with an error and deletes nothing. This is the option for queues, sessions and Horizon: the application reports the error instead of losing a job without anyone knowing.
- Discard least used: deletes the least used keys to make room. Only for caching; with queues or sessions you would lose jobs and log users out.
Changing the settings restarts Redis. With Every second it recovers its data when it comes back; if you switch to No persistence, it starts empty.
Actions
- Settings: change memory, persistence and behaviour when full.
- Restart: stops it and starts it again. With persistence, it keeps the data.
- Flush: deletes everything it holds, in all its databases: pending jobs in the queues, open sessions (users will have to log in again) and Horizon metrics. It cannot be undone.
- Disable: stops it and removes it, which frees its persistent process slot. The application will lose the connection: change its
.envfirst. What it stored stays in your account in case you enable it again, unless you tick Also delete what it has stored.
You can check that it responds over SSH, with your username instead of USUARIO:
valkey-cli -s /home/USUARIO/.hostsuar/redis/redis.sock ping valkey-cli -s /home/USUARIO/.hostsuar/redis/redis.sock info memory
The first replies PONG; the second shows the memory used (used_memory_human) and the limit (maxmemory_human).
Connect it from Laravel
Enable the redis (PhpRedis) extension in the application's PHP version and, if your workers use another version, in that one too. Then, in .env:
REDIS_CLIENT=phpredis REDIS_HOST=/home/USUARIO/.hostsuar/redis/redis.sock REDIS_PORT=0 REDIS_PASSWORD=null QUEUE_CONNECTION=redis SESSION_DRIVER=redis
Replace USUARIO with your cPanel username. With Deploy+, edit .env from the repository menu; if you cache the configuration, run php artisan config:cache again or deploy again. Check the connection:
php artisan tinker --execute="dump(Illuminate\Support\Facades\Redis::connection()->ping());"
It should show true.
Before switching connections, bear in mind what already exists:
- Queues: jobs waiting in the database do not move to Redis. Let the database queue empty before changing
QUEUE_CONNECTION, or keep a worker on thedatabaseconnection for a while. - Sessions: sessions stored in the database are not moved. When you change
SESSION_DRIVER, users will have to log in again.
To process the queues you need a running worker: create it in Tools > Processes as a Queue worker or use Horizon. You will find it in persistent processes.
With Redis Cache at the same time
If you want the cache in Redis Cache and everything else in persistent Redis, make the cache connection in config/database.php read its own variables. In the cache connection, change the host and port:
'host' => env('REDIS_CACHE_HOST', env('REDIS_HOST', '127.0.0.1')), 'port' => env('REDIS_CACHE_PORT', env('REDIS_PORT', '6379')),
And in .env:
REDIS_HOST=/home/USUARIO/.hostsuar/redis/redis.sock REDIS_PORT=0 REDIS_CACHE_HOST=/tmp/redis.sock REDIS_CACHE_PORT=0 CACHE_STORE=redis
The redis store in config/cache.php uses the cache connection for data and the default one for locks, so the locks from Cache::lock() and withoutOverlapping() stay in persistent Redis, which does not evict them.
If you only have persistent Redis, keep the cache in the database or, if you put it in Redis, give what you store an expiry: with Don't lose data, a cache that grows without expiring ends up filling the memory and blocking the queues too.
Horizon
Horizon needs queues in Redis and a process to keep it running:
- Enable persistent Redis and connect Laravel as in the previous section, with
QUEUE_CONNECTION=redis. - Install Horizon in your project with
composer require laravel/horizonandphp artisan horizon:install. It needs thepcntlandposixextensions: if Composer warns that they are missing, enable them in the PHP version you are going to use. - Check
config/horizon.php. Theproductionsupervisor allows up to 10 workers by default, and each one uses its own memory within your account's resources: setmaxProcessesto what your application needs, for example 2 or 3 on Avanza. - Decide who can see the
/horizondashboard in thegate()method ofapp/Providers/HorizonServiceProvider.php. Outside the local environment, only the people you authorise there can get in. - In Tools > Processes, add a Horizon process with the application's folder and its PHP version. Do not also create a queue worker for the same queues.
- If you deploy with Deploy+, do not add anything to the script: after activating each release, and also when rolling back to a previous one, it restarts that application's Horizon process. The script runs before the release is activated, so a
horizon:terminatefrom there would make Horizon start again on the previous one. If you deploy some other way, runphp artisan horizon:terminateonce the new code is in place. - If you want the metrics charts, schedule
horizon:snapshotevery five minutes inroutes/console.php:
use Illuminate\Support\Facades\Schedule; Schedule::command('horizon:snapshot')->everyFiveMinutes();
Horizon with Redis Cache is not safe: if that cache is flushed or fills up, pending jobs are lost.
Backups
The data lives in your account, in ~/.hostsuar/redis/, and is included in the daily backups like the rest of your files.
Restoring that folder takes Redis back to the state it was in on that day: the jobs that were pending then would go back into the queue, even if they had been processed afterwards. If you need to restore it, first stop persistent Redis from Tools > Processes and start it again when the restore has finished.
You may also find useful
- Integrate LiteSpeed Cache with Laravel Integrate the LiteSpeed server cache with Laravel using Composer and apply the package's middleware...
- Set up Redis as an object cache Activate a Redis instance for object caching and connect to it over a Unix socket from WordPress, Pr...
- What the object cache is and how to set it up in WordPress Explains the WordPress object cache, when it helps and how to make it persistent with Redis without...
- AccelerateWP: features, availability and configuration Details the free and premium AccelerateWP features for WordPress, including caching, file optimisati...
Something wrong or out of date? Tell us and we will review it.