redis-cli llen queues:default and hope. That was my queue monitoring for years. Horizon replaces it with a real dashboard, and I did not know how much I needed one until I saw it.

The mental shift matters more than the UI. dispatch() is the beginning of the work, not the end. The job still has to wait in Redis, run, maybe fail, maybe retry. All of that was invisible. Now it is on one screen: throughput, wait time per queue, failed jobs with the full payload and the exception.

Configuration is one file. I split queues by priority:

'production' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue'      => ['payments', 'default', 'emails'],
        'balance'    => 'auto',
        'processes'  => 10,
    ],
],

balance => auto moves worker processes to the queue that falls behind. Sounds like magic. Works fine, at least on the one project I watch daily now.

The most useful metric turned out to be wait time. Throughput tells you how busy you are. Wait time tells you how much your users suffer. A payment confirmation job that waits ninety seconds behind a pile of newsletter jobs is a bug, even when every job succeeds.

Second lesson. At some point more workers stop helping. We went from ten processes to twenty and throughput did not move. Jobs were spending their time waiting on MySQL and one slow external API, and twenty workers means twenty connections waiting in parallel. The dashboard shows this honestly: jobs per minute flat, wait time still growing. When you see that picture, the fix is somewhere else than the queue config.

For years I answered “how is the queue” with a number from redis-cli. I was answering a different question.