Failed jobs — failed_jobs table, retry artisan command
Concept
Laravel Horizon is an official Laravel package that provides a beautiful dashboard for monitoring Redis queues. It offers real-time visibility into job throughput, runtime, and failures, and adds process management capabilities.
What Horizon adds:
- Real-time dashboard: throughput, runtime, failures per queue.
- Job search by job name, ID, or status.
- Failed job browser with retry from the UI.
- Automatic worker management: Horizon manages PHP worker processes automatically, scaling up/down based on queue depth.
- Metrics retention: stores recent job metrics in Redis for historical analysis.
Supervisor mode: Horizon acts as a supervisor process. Instead of running queue:work manually, you run php artisan horizon. Horizon manages worker pools internally.
Configuration (config/horizon.php):
environments: Configure different worker counts and queues per environment (production vs local).defaults: Named supervisor configurations with queue assignment, processes count, timeout.supervisor-1: Supervisor watching specific queues.
Deployment: Always run php artisan horizon:terminate before deploying new code. Horizon will auto-restart workers with the new code after receiving the terminate signal. In production, use a process manager (Supervisor, systemd) to run horizon and keep it alive.
Authorization: Horizon::auth() callback in HorizonServiceProvider controls who can view the dashboard.
Code Example
# Installation
# composer require laravel/horizon
# php artisan horizon:install
# php artisan migrate
// config/horizon.php
'environments' => [
'production' => [
'supervisor-1' => [
'maxProcesses' => 10, // up to 10 workers
'balanceMaxShift' => 1, // scale one process at a time
'balanceCooldown' => 3, // wait 3s between scale events
],
],
'local' => [
'supervisor-1' => [
'maxProcesses' => 3,
],
],
],
'defaults' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default', 'emails', 'orders'],
'balance' => 'auto', // auto-balance workers across queues
'minProcesses' => 1,
'maxProcesses' => 10,
'timeout' => 60,
'tries' => 3,
'nice' => 0,
],
],
// Starting Horizon
// php artisan horizon
// php artisan horizon:status — check if running
// php artisan horizon:pause — pause processing
// php artisan horizon:continue — resume
// php artisan horizon:terminate — graceful shutdown
// Access control — HorizonServiceProvider::boot()
\Laravel\Horizon\Horizon::auth(function($request) {
return $request->user()?->isAdmin() ?? false;
// Or: return in_array($request->user()?->email, config('horizon.allowed_emails'));
});
// Dashboard URL
// /horizon — requires authentication as configured above
// Supervisor config for production (keep Horizon running)
// /etc/supervisor/conf.d/laravel-horizon.conf
// [program:laravel-horizon]
// process_name=%(program_name)s
// command=php /var/www/html/artisan horizon
// autostart=true
// autorestart=true
// user=www-data
// redirect_stderr=true
// stdout_logfile=/var/www/html/storage/logs/horizon.log