laravel/horizon
Laravel Horizon adds a beautiful dashboard and code-driven configuration for Laravel Redis queues. Monitor throughput, runtime, and failures, manage workers and supervisors from a single config file, and keep queue operations visible and maintainable.
Installation:
composer require laravel/horizon
php artisan horizon:install
This publishes the Horizon configuration file (config/horizon.php) and sets up the necessary Redis connection.
Configure Redis:
Ensure your config/queue.php uses Redis as the default connection:
'default' => env('QUEUE_CONNECTION', 'redis'),
Run Horizon:
php artisan horizon
Access the dashboard at http://your-app.test/horizon.
dispatch(new ProcessPodcast)->onFailure(function ($e) {
// Log or notify about failure
});
Job Supervision:
config/horizon.php to manage worker pools:
'supervisors' => [
'default' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
'processes' => 8,
'tries' => 3,
],
],
processes based on server resources and job complexity.Batch Processing:
dispatch()->onQueue('batch-jobs') and monitor batch metrics (e.g., throughput, failures) in the Batches tab.Delayed Jobs:
dispatch()->delay(now()->addMinutes(10)) and track delayed jobs in the Delayed tab.Custom Metrics:
event(new JobProcessed($job));
config/horizon.php:
'events' => [
\App\Events\JobProcessed::class,
],
Queue Workers:
Run Horizon alongside Laravel’s queue workers (e.g., php artisan queue:work --daemon in production) for redundancy.
php artisan horizon & php artisan queue:work --daemon
Environment-Specific Config:
Use environment variables to toggle features (e.g., HORIZON_ENABLED=false to disable in staging):
'enabled' => env('HORIZON_ENABLED', true),
CI/CD Pipelines: Add Horizon to deployment scripts to ensure queue monitoring is always available:
# In deploy.sh
php artisan horizon:terminate
php artisan horizon > /dev/null 2>&1 &
Redis Connection Issues:
Redis connection not found.QUEUE_CONNECTION=redis in .env and that Redis is running. Use php artisan horizon:terminate to clear stale connections.Memory Leaks:
horizon:flush to clear old jobs:
php artisan horizon:flush --hours=24
Job Stuck in "Pending":
redis-cli LPUSH failed:12345 '{"job": "...", "payload": {...}}'
Dashboard Not Loading:
storage/logs/laravel.log for Redis or PHP errors. Ensure the horizon middleware is registered in app/Http/Kernel.php:
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\App\Http\Middleware\Horizon::class, // <-- Add this
],
Log Job Payloads:
Enable Horizon’s debug mode in config/horizon.php:
'debug' => env('HORIZON_DEBUG', false),
Logs job payloads to storage/logs/horizon.log.
Redis Cluster Support:
Configure redis-cluster connection in config/queue.php and set connection: redis-cluster in config/horizon.php (v5.46.0+).
Custom Job Views: Override default job views by publishing assets:
php artisan vendor:publish --tag=horizon-assets
Edit files in resources/views/vendor/horizon/.
Custom Job Badges:
Add badges to job listings via the getBadges method in your job class:
public function getBadges()
{
return ['priority' => $this->priority];
}
Webhook Notifications: Trigger webhooks on job events (e.g., failure) using Horizon’s event system:
Horizon::on('job.failed', function ($job, $exception) {
Http::post('https://your-webhook.url', [
'job_id' => $job->id,
'exception' => $exception->getMessage(),
]);
});
Supervisor Events:
Listen for supervisor events (e.g., SupervisorStarted) to log worker lifecycle:
Horizon::on('supervisor.started', function ($supervisor) {
Log::info("Supervisor {$supervisor->name} started with {$supervisor->processes} processes.");
});
Silenced Tags:
Exclude specific jobs from monitoring using silenced_tags:
'supervisors' => [
'default' => [
'silenced_tags' => ['logs', 'notifications'],
],
],
Jobs with these tags won’t appear in Horizon’s UI.
Private Tunnel Restrictions:
Disable private tunnel access in config/horizon.php for local environments:
'private_tunnel' => [
'enabled' => env('HORIZON_PRIVATE_TUNNEL', false),
],
Job ID Clickability: Job IDs in the dashboard are clickable by default (v5.40.0+). Disable via:
'clickable_job_ids' => false,
Batch Searching: Use wildcard searches for batches (v5.45.0+):
php artisan horizon:batches --search="order*"
```markdown
### Pro Tips
- **Zero-Downtime Deployments**:
Use `php artisan horizon:terminate` followed by `php artisan horizon` to restart workers without dropping jobs.
- **Monitoring Alerts**:
Integrate Horizon with tools like Datadog or Prometheus by exposing metrics via:
```php
Horizon::metrics(function () {
return [
'jobs_processed' => Job::where('processed_at', '>', now()->subHour())->count(),
];
});
app/Console/Commands and register them in HorizonServiceProvider:
protected function schedule(Schedule $schedule)
{
$schedule->command(new CustomHorizonCommand)->hourly();
}
How can I help you explore Laravel packages today?