Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions resources/boost/skills/configure-horizon/SKILL.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
name: configuring-horizon
description: "Configures Laravel Horizon for Redis queue management. Activate when the user explicitly mentions Horizon by name. Covers Horizon installation, supervisor configuration, worker processes, dashboard authorization, auto-scaling, balancing strategies, job monitoring, metrics, tags, and notifications. Also applies when troubleshooting Horizon-specific issues such as blank metrics, LongWaitDetected alerts, or misconfigured Horizon workers. Do NOT activate for generic queue, Redis, or job monitoring questions that do not mention Horizon."
license: MIT
metadata:
author: laravel
---
@php
/** @var \Laravel\Boost\Install\GuidelineAssist $assist */
@endphp
# Horizon Configuration

## When to Apply

Activate this skill when the user explicitly mentions **Horizon** by name. Examples:

- Installing or configuring Horizon
- Setting up Horizon supervisors or worker processes
- Restricting access to the Horizon dashboard
- Configuring Horizon auto-scaling or balancing strategies
- Setting up Horizon job monitoring, tags, metrics, or notifications
- Troubleshooting Horizon blank metrics or LongWaitDetected alerts

Do NOT activate for generic queue workers, Redis configuration, or job monitoring questions that do not mention Horizon.

## Documentation

Use `search-docs` for detailed Horizon patterns and documentation covering configuration, supervisors, balancing, dashboard authorization, tags, notifications, metrics, and deployment.

For deeper guidance on specific topics, read the relevant reference file before implementing:

- `references/supervisors.md` covers supervisor blocks, balancing strategies, multi-queue setups, and auto-scaling
- `references/notifications.md` covers LongWaitDetected alerts, notification routing, and the `waits` config
- `references/tags.md` covers job tagging, dashboard filtering, and silencing noisy jobs
- `references/metrics.md` covers the blank metrics dashboard, snapshot scheduling, and retention config

## Basic Usage

### Installation

```bash
{{ $assist->artisanCommand('horizon:install') }}
```

### Supervisor Configuration

Define supervisors in `config/horizon.php`. The `environments` array merges into `defaults` and does not replace the whole supervisor block:

@boostsnippet("Supervisor Config", "php")
'defaults' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
'minProcesses' => 1,
'maxProcesses' => 10,
'tries' => 3,
],
],

'environments' => [
'production' => [
'supervisor-1' => ['maxProcesses' => 10, 'balanceCooldown' => 3],
],
'local' => [
'supervisor-1' => ['maxProcesses' => 2],
],
],
@endboostsnippet

### Dashboard Authorization

Restrict access in `App\Providers\HorizonServiceProvider`:

@boostsnippet("Dashboard Gate", "php")
protected function gate(): void
{
Gate::define('viewHorizon', function (User $user) {
return $user->is_admin;
});
}
@endboostsnippet

## Verification

1. Run `{{ $assist->artisanCommand('horizon') }}` and visit `/horizon`
2. Confirm dashboard access is restricted as expected
3. Check that metrics populate after scheduling `horizon:snapshot`

## Common Pitfalls

- Horizon only works with the Redis queue driver. Other drivers such as database and SQS are not supported.
- Redis Cluster is not supported. Horizon requires a standalone Redis connection.
- Always check `config/horizon.php` before making changes to understand the current supervisor and environment configuration.
- The `environments` array overrides only the keys you specify. It merges into `defaults` and does not replace it.
- The timeout chain must be ordered: job `timeout` less than supervisor `timeout` less than `retry_after`. The wrong order can cause jobs to be retried before Horizon finishes timing them out.
- The metrics dashboard stays blank until `horizon:snapshot` is scheduled. Running `php artisan horizon` alone does not populate metrics.
- Always use `search-docs` for the latest Horizon documentation rather than relying on this skill alone.
21 changes: 21 additions & 0 deletions resources/boost/skills/configure-horizon/references/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Metrics & Snapshots

## Where to Find It

Search with `search-docs`:
- `"horizon metrics snapshot"` for the snapshot command and scheduling
- `"horizon trim snapshots"` for retention configuration

## What to Watch For

### Metrics dashboard stays blank until `horizon:snapshot` is scheduled

Running `php artisan horizon` does not populate metrics automatically. The metrics graph is built from snapshots, so `php artisan horizon:snapshot` must be scheduled to run every 5 minutes via Laravel's scheduler.

### Register the snapshot in the scheduler rather than running it manually

A single manual run populates the dashboard momentarily but will not keep it updated. Search `"horizon metrics snapshot"` for the exact scheduler registration syntax, which differs between Laravel 10 and 11+.

### `metrics.trim_snapshots` is a snapshot count, not a time duration

The `trim_snapshots.job` and `trim_snapshots.queue` values in `config/horizon.php` are counts of snapshots to keep, not minutes or hours. With the default of 24 snapshots at 5-minute intervals, that provides 2 hours of history. Increase the value to retain more history at the cost of Redis memory usage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Notifications & Alerts

## Where to Find It

Search with `search-docs`:
- `"horizon notifications"` for Horizon's built-in notification routing helpers
- `"horizon long wait detected"` for LongWaitDetected event details

## What to Watch For

### `waits` in `config/horizon.php` controls the LongWaitDetected threshold

The `waits` array (e.g., `'redis:default' => 60`) defines how many seconds a job can wait in a queue before Horizon fires a `LongWaitDetected` event. This value is set in the config file, not in Horizon's notification routing. If alerts are firing too often or too late, adjust `waits` rather than the routing configuration.

### Use Horizon's built-in notification routing in `HorizonServiceProvider`

Configure notifications in the `boot()` method of `App\Providers\HorizonServiceProvider` using `Horizon::routeMailNotificationsTo()`, `Horizon::routeSlackNotificationsTo()`, or `Horizon::routeSmsNotificationsTo()`. Horizon already wires `LongWaitDetected` to its notification sender, so the documented setup is notification routing rather than manual listener registration.

### Failed job alerts are separate from Horizon's documented notification routing

Horizon's 12.x documentation covers built-in long-wait notifications. Do not assume the docs provide a `JobFailed` listener example in `HorizonServiceProvider`. If a user needs failed job alerts, treat that as custom queue event handling and consult the queue documentation instead of Horizon's notification-routing API.
27 changes: 27 additions & 0 deletions resources/boost/skills/configure-horizon/references/supervisors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Supervisor & Balancing Configuration

## Where to Find It

Search with `search-docs` before writing any supervisor config, as option names and defaults change between Horizon versions:
- `"horizon supervisor configuration"` for the full options list
- `"horizon balancing strategies"` for auto, simple, and false modes
- `"horizon autoscaling workers"` for autoScalingStrategy details
- `"horizon environment configuration"` for the defaults and environments merge

## What to Watch For

### The `environments` array merges into `defaults` rather than replacing it

The `defaults` array defines the complete base supervisor config. The `environments` array patches it per environment, overriding only the keys listed. There is no need to repeat every key in each environment block. A common pattern is to define `connection`, `queue`, `balance`, `autoScalingStrategy`, `tries`, and `timeout` in `defaults`, then override only `maxProcesses`, `balanceMaxShift`, and `balanceCooldown` in `production`.

### Use separate named supervisors to enforce queue priority

Horizon does not enforce queue order when using `balance: auto` on a single supervisor. The `queue` array order is ignored for load balancing. To process `notifications` before `default`, use two separately named supervisors: one for the high-priority queue with a higher `maxProcesses`, and one for the low-priority queue with a lower cap. The docs include an explicit note about this.

### Use `balance: false` to keep a fixed number of workers on a dedicated queue

Auto-balancing suits variable load, but if a queue should always have exactly N workers such as a video-processing queue limited to 2, set `balance: false` and `maxProcesses: 2`. Auto-balancing would scale it up during bursts, which may be undesirable.

### Set `balanceCooldown` to prevent rapid worker scaling under bursty load

When using `balance: auto`, the supervisor can scale up and down rapidly under bursty load. Set `balanceCooldown` to the number of seconds between scaling decisions, typically 3 to 5, to smooth this out. `balanceMaxShift` limits how many processes are added or removed per cycle.
21 changes: 21 additions & 0 deletions resources/boost/skills/configure-horizon/references/tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Tags & Silencing

## Where to Find It

Search with `search-docs`:
- `"horizon tags"` for the tagging API and auto-tagging behaviour
- `"horizon silenced jobs"` for the `silenced` and `silenced_tags` config options

## What to Watch For

### Eloquent model jobs are tagged automatically without any extra code

If a job's constructor accepts Eloquent model instances, Horizon automatically tags the job with `ModelClass:id` such as `App\Models\User:42`. These tags are filterable in the dashboard without any changes to the job class. Only add a `tags()` method when custom tags beyond auto-tagging are needed.

### `silenced` hides jobs from the dashboard completed list but does not stop them from running

Adding a job class to the `silenced` array in `config/horizon.php` removes it from the completed jobs view. The job still runs normally. This is a dashboard noise-reduction tool, not a way to disable jobs.

### `silenced_tags` hides all jobs carrying a matching tag from the completed list

Any job carrying a matching tag string is hidden from the completed jobs view. This is useful for silencing a category of jobs such as all jobs tagged `notifications`, rather than silencing specific classes.