Packages Tutorial

Mastering Laravel Horizon: Advanced Queue Management and Monitoring

Admin User
Admin User
Apr 28, 2026
6 min read

Key Takeaways

  • # Mastering Laravel Horizon: Advanced Queue Management and Monitoring
  • Laravel applications often rely on queues for handling time-consuming tasks in the backgr...

Mastering Laravel Horizon: Advanced Queue Management and Monitoring

Laravel applications often rely on queues for handling time-consuming tasks in the background, improving responsiveness and user experience. While Laravel's built-in queue system is robust, managing and monitoring these queues can become complex as your application scales. This is where Laravel Horizon comes steps in – providing a beautiful dashboard and code-driven configuration for your Redis-powered Laravel queues.

Horizon offers real-time insights into your queue's throughput, runtime, and job failures, making it an indispensable tool for applications heavily relying on queues.

Prerequisites #

Before diving into Horizon, ensure your development environment and Laravel application meet the following requirements:

  • A Laravel 8.x or newer application.

  • PHP 7.4 or newer.

  • Composer installed.

  • Redis server installed and configured. Laravel's default queue driver redis should be configured in your .env file:

    QUEUE_CONNECTION=redis
    

Installation #

Installing Laravel Horizon is straightforward. First, add the package to your project via Composer:

composer require laravel/horizon

Next, publish Horizon's assets and configuration files using the horizon:install Artisan command:

php artisan horizon:install

This command will publish the config/horizon.php configuration file and register an HorizonServiceProvider in your config/app.php. Finally, run migrations to create the necessary database tables that Horizon uses for storing metrics and failed jobs:

php artisan migrate

Configuration #

The primary configuration file for Horizon is config/horizon.php. This file allows you to define your supervisors, workers, and specific configurations for different environments.

Key configuration sections include:

  • environments: Define different queue configurations for environments like production, local, etc. Each environment can have multiple supervisors, each managing its own set of workers and queues.

    // config/horizon.php
    
    'environments' => [
        'production' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['default', 'emails'], // Queues this supervisor will process
                'balance' => 'auto', // Balancing strategy
                'processes' => 10,   // Max processes for this supervisor
                'tries' => 3,        // Number of times to retry a job
                'timeout' => 60,     // Max seconds a job can run
                'sleep' => 3,        // Seconds to sleep when no jobs are available
            ],
        ],
    
        'local' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['default'],
                'balance' => 'simple',
                'processes' => 3,
                'tries' => 3,
            ],
        ],
    ],
    
  • balance: This setting determines how Horizon balances worker processes across your queues. Choosing the right strategy can significantly impact your application's performance.

    • simple: Distributes incoming jobs evenly among available workers.
    • auto: Horizon automatically adjusts the number of workers per queue based on the queue's load and pending jobs. This dynamic scaling requires php >= 7.1 and the pcntl extension.
    • false: Disables balancing, allowing you to manually define the number of processes for each queue.
  • metrics: Configures the retention period for metrics and failed jobs data, helping you manage storage and performance.

Running Horizon #

To start Horizon in your development environment, simply run the Artisan command:

php artisan horizon

This command will launch your queue workers and make the Horizon dashboard accessible. The dashboard is typically available at the /horizon URL of your application (e.g., http://localhost:8000/horizon).

Securing the Dashboard #

For production environments, it's crucial to secure access to the Horizon dashboard. You can restrict access by defining an authorization gate in your AuthServiceProvider:

// app/Providers/AuthServiceProvider.php

use Laravel\Horizon\Horizon;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Horizon::auth(function ($request) {
        // Return true to allow access, false to deny.
        // For example, only allow users with an 'isAdmin' method that returns true.
        return $request->user() && $request->user()->isAdmin();
    });
}

Key Features of Laravel Horizon #

Laravel Horizon is packed with features designed to simplify queue management:

  1. Dashboard Overview: Provides a real-time summary of your queues, including job throughput, failed jobs, and worker status, all from an intuitive UI.

  2. Metrics: Visual graphs display critical performance indicators like job throughput, wait times, and run times over various periods. These metrics are invaluable for identifying bottlenecks and optimizing your queue performance.

  3. Failed Jobs: A dedicated section allows you to view, retry, or delete failed jobs. You can filter failed jobs by exception type, queue, or specific tags for easier debugging.

  4. Recent Jobs: Monitor jobs as they are processed, with detailed information on their status (pending, processing, completed, failed), queue, and full payload. This is excellent for debugging individual jobs.

  5. Tags: Horizon can automatically tag jobs based on the Eloquent models attached to them. This powerful feature allows you to filter job history by specific models (e.g., all jobs related to a User with ID 1). You can also manually define tags for your jobs:

    // app/Jobs/ProcessOrder.php
    
    class ProcessOrder implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        public $order;
    
        public function __construct(Order $order)
        {
            $this->order = $order;
        }
    
        public function handle()
        {
            // Process the order...
        }
    
        public function tags()
        {
            return ['order:' . $this->order->id, 'user:' . $this->order->user->id];
        }
    }
    
  6. Notifications: Configure Horizon to notify you via Slack or email when a queue has an unusually long wait time or a batch of jobs fails, enabling proactive problem resolution.

    // app/Providers/AppServiceProvider.php (or HorizonServiceProvider)
    
    use Laravel\Horizon\Horizon;
    
    public function boot()
    {
        // ...
    
        Horizon::routeSlackNotificationsTo('your-slack-webhook-url');
        Horizon::routeMailNotificationsTo('[email protected]');
    
        // Example: Notify if the 'default' queue has a wait time exceeding 1 minute
        Horizon::waitCallbacks([
            function () {
                return Horizon::onQueue('default')->waits()->exceeding(1)->minutes();
            },
        ]);
    }
    

Production Deployment #

For production environments, you should use a process manager like supervisord or systemd to keep Horizon running continuously. This ensures that your queue workers are always active and automatically restarted if they crash, maintaining the reliability of your application.

Here's an example supervisord configuration (/etc/supervisor/conf.d/horizon.conf):

[program:horizon]
process_name=%(program_name)s
command=php /var/www/your-app/artisan horizon
autostart=true
autorestart=true
user=www-data             ; Or your web server user (e.g., 'nginx', 'forge')
redirect_stderr=true
stdout_logfile=/var/www/your-app/storage/logs/horizon.log
stopwaitsecs=3600         ; Wait for jobs to finish before stopping (optional, but recommended)

After creating or updating the configuration file, update and start supervisord:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon

Conclusion #

Laravel Horizon transforms queue management from a complex, command-line-driven task into an intuitive, visually-driven experience. Its real-time monitoring, intelligent balancing strategies, and robust failure handling capabilities make it an essential package for any production-ready Laravel application utilizing Redis queues. By leveraging Horizon, you can achieve more reliable, performant, and easily debuggable applications, ensuring your background tasks run smoothly and efficiently.

FAQs

What is the main benefit of using Laravel Horizon over native Laravel queues?
Laravel Horizon provides a beautiful, real-time dashboard for monitoring your Redis queues, offering insights into job throughput, failed jobs, and worker performance, which native Laravel queues don't offer out-of-the-box. It simplifies queue management and debugging significantly.
How do I ensure Laravel Horizon runs continuously in production?
For production environments, you should use a process monitor like Supervisord or Systemd to manage the `php artisan horizon` process. This ensures Horizon starts automatically on server boot and restarts if it crashes, maintaining continuous queue processing and application reliability.

Want more content like this?

Explore more tutorials in the Packages section.

Explore Packages

You might also like