Laravel Horizon is an elegant dashboard and code-driven configuration system for your Redis queues. It provides real-time insights into your queue's health, throughput, and failed jobs, making it an indispensable tool for applications heavily relying on asynchronous processing.
Why Use Laravel Horizon?
Laravel's queue system is powerful, but without a dedicated monitoring tool, understanding its current state, identifying bottlenecks, or managing failed jobs can be challenging. Horizon addresses this by offering:
1. Real-time Dashboard: A beautiful web interface that displays active, pending, completed, and failed jobs across all your queues. You can see job throughput, processing times, and memory usage at a glance.
2. Worker Management: Horizon allows you to configure, scale, pause, and terminate queue workers directly from its code-driven configuration file (`config/horizon.php`). It automatically manages 'supervisors' (long-running processes that manage your queue workers), ensuring your workers are always running and correctly configured.
3. Failed Job Management: Easily view details of failed jobs, including the exception trace. You can retry failed jobs individually or in bulk, or delete them directly from the dashboard.
4. Job Metrics: Provides statistical data on job execution times and queue sizes, helping you identify slow jobs or overloaded queues.
5. Notifications: Can be configured to send notifications when queues have a high backlog or when jobs fail.
6. Code-Driven Configuration: All aspects of your queue workers (connections, queues, timeout, tries, etc.) are defined in a single configuration file, making it easy to manage and version control.
How It Works:
Horizon leverages Redis as its underlying queue backend. It uses Redis to store queue information, job payloads, and its own internal metrics. The `php artisan horizon` command starts the Horizon process, which acts as a supervisor, managing your queue workers and pushing data to Redis for the dashboard. The Horizon dashboard then reads this data from Redis to provide its real-time views.
Benefits:
* Enhanced Visibility: Get a clear picture of your queue's activity and performance.
* Simplified Management: Easily manage workers and failed jobs without complex command-line interactions.
* Improved Debugging: Quickly identify and address issues with failed jobs.
* Scalability: Efficiently manage a large number of queues and workers with robust supervisor management.
In essence, Laravel Horizon transforms your Redis-backed queues from a black box into a transparent, manageable system.
Example Code
<?php
// 1. Installation: Install Horizon via Composer
// composer require laravel/horizon
// php artisan horizon:install
// php artisan migrate // If you want to store job tags in a database
// 2. Configure your .env file to use Redis for queues
// QUEUE_CONNECTION=redis
// 3. A simple queue job example (app/Jobs/ProcessPodcast.php)
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/
* Create a new job instance.
*
* @param array $podcast
* @return void
*/
public function __construct(array $podcast)
{
$this->podcast = $podcast;
}
/
* Execute the job.
*
* @return void
*/
public function handle()
{
// Simulate a time-consuming task
sleep(5);
Log::info('Processing podcast: ' . $this->podcast['title']);
// You might do something like:
// Podcast::create($this->podcast);
}
}
// 4. Dispatching the job from a controller or route
// Example in a route file (web.php) or a controller method:
use App\Jobs\ProcessPodcast;
use Illuminate\Support\Facades\Route;
Route::get('/process-podcast', function () {
$podcastData = [
'title' => 'My Awesome Podcast Episode',
'url' => 'http://example.com/episode.mp3',
'duration' => 3600
];
// Dispatch the job to the queue
ProcessPodcast::dispatch($podcastData);
return 'Podcast processing job dispatched!';
});
// 5. Basic Horizon configuration (config/horizon.php snippet)
// This file is published by `php artisan horizon:install`
/*
|--------------------------------------------------------------------------
| Horizon Redis Connections
|--------------------------------------------------------------------------
|
| Each of the connection configurations in the 'connections' array configures
| the Redis connection that Horizon will use to store all of its queue
| metadata. These connections must be configured in your 'database' config.
|
*/
'connections' => [
'redis' => [
'connection' => 'default',
'queue' => ['default'], // The default queue Horizon will listen to
],
],
/*
|--------------------------------------------------------------------------
| Horizon Supervisors
|--------------------------------------------------------------------------
|
| You may configure the supervisors for your application here. These supervisors
| will be started by the 'horizon' command and will run all of your workers.
|
*/
'supervisors' => [
'default' => [
'connection' => 'redis',
'queue' => ['default', 'high', 'low'], // Queues this supervisor will process
'balance' => 'auto', // Auto-balance workers across queues
'processes' => 1, // Number of worker processes to start
'tries' => 3, // How many times a job should be attempted
'timeout' => 60, // How many seconds a job can run before timing out
],
],
// 6. Starting Horizon
// After configuring and dispatching jobs, you start Horizon to process them:
// php artisan horizon
// You can then access the Horizon dashboard in your browser at:
// http://your-app-domain/horizon
// For production, you would typically use a process manager like Supervisor
// to keep `php artisan horizon` running indefinitely.








Laravel Horizon