Skyline

Queue control

Pausing & resuming queues

Pause every worker, one supervisor, or a single queue — then resume.

Pausing is the first thing you want during an incident: a downstream API is failing, a migration is halfway through, a bad deploy is churning through jobs. Skyline lets you stop processing at three levels of granularity — everything, one supervisor, or a single queue — and resume when you are ready. Jobs simply accumulate until you do.

Three levels

Scope How Effect
Everything php artisan horizon:pause Every worker on every supervisor stops picking up jobs.
One supervisor php artisan horizon:pause-supervisor {name} Only that supervisor's workers stop.
One queue Dashboard, or the HTTP API Workers keep serving their other queues and skip only the paused one.

Each has a matching resume: horizon:continue, horizon:continue-supervisor {name}, and the Resume button (or a DELETE to the pause endpoint).

Global and per-supervisor pause

These are the upstream Horizon commands, unchanged. They work by signalling the master supervisor process, so they take effect within a loop iteration and survive nothing — a restarted supervisor comes back unpaused.

# Stop everything, then resume
php artisan horizon:pause
php artisan horizon:continue

# Stop a single supervisor by name
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1

Skyline adds pause and resume buttons for these to the dashboard, so an operator does not need shell access on a worker box to stop processing.

Per-queue pause

Pausing a whole supervisor is a blunt instrument when one queue is the problem and the rest are healthy. Skyline exposes Pause and Resume per queue, straight from the dashboard.

A worker serving high,default,low whose low queue is paused keeps processing high and default at full speed and simply skips low when it comes around in the pickup loop. Autoscaling is aware of it too: the supervisor will not scale processes onto a paused queue.

Per-queue pause state lives in your default cache store, not in the worker's memory, which is what lets the dashboard, the supervisors and the workers all agree on it. It therefore survives a worker restart — a queue you paused stays paused until something resumes it.

Requirements

Per-queue pausing is built on Laravel's native queue-pause API, and needs a Laravel version that provides it. It also needs a shared cache store: the array and null stores cannot carry state between the dashboard and the worker processes, so they are rejected.

When either requirement is unmet, Skyline detects it at runtime: the dashboard hides the per-queue Pause buttons and shows an explanatory banner, and the API endpoints respond 409 Conflict. Nothing else is affected — global and per-supervisor pause keep working.

Grouped queues

A non-balancing supervisor may serve a comma-joined group such as high,default,low. Skyline pauses and reports on the individual sub-queues: the group is shown as paused only when every sub-queue in it is paused. Pausing low alone leaves the group running.

From the API

The dashboard buttons are backed by two endpoints, which you can call from a deploy script or an incident runbook:

# Pause the "exports" queue on the "redis" connection
curl -X POST https://example.com/horizon/api/queues/redis/exports/pause

# Resume it
curl -X DELETE https://example.com/horizon/api/queues/redis/exports/pause

Both return 204 No Content on success, and 409 Conflict when queue pausing is not supported in the environment.

The calls above are illustrative

These endpoints sit behind the same viewHorizon gate and web middleware as the dashboard itself, so a real script has to carry a session cookie and a CSRF token — a bare curl gets a redirect or a 419, not a paused queue. See the HTTP API reference.

Pausing is not draining

Pausing stops workers from picking up new jobs. It does not stop jobs already in flight — those run to completion — and it does not stop producers from dispatching. A paused queue keeps growing.

That is usually what you want during an incident, but it means a long pause on a busy queue has a cost you should plan for: the backlog you will have to work through on resume, and the Redis memory it occupies until then. If the jobs are genuinely unwanted rather than merely untimely, empty the queue instead — see Dashboard operations.

Queue control, not just queue monitoring.

Skyline is a drop-in replacement for Laravel Horizon that lets you act on what you see — pause a queue, jump a job to the front, drain a backlog.

Sign up for early access