Priority queues, and the starvation they cause

Running a worker over two queues in priority order means the low-priority queue is only touched when the high one is empty — which under sustained load is never.

# strict priority: 'default' starves whenever 'high' has work
$ php artisan queue:work --queue=high,default

# what usually works better: dedicated workers
$ php artisan queue:work --queue=high     &  # 2 processes
$ php artisan queue:work --queue=default  &  # 2 processes

# the failure mode: an export job never runs, and nobody
# notices until somebody asks where the report is.

Dedicating workers guarantees throughput on both queues at the cost of some idle capacity, which is almost always the right trade. Starvation is silent — the queue depth graph shows one queue growing and nothing alerts unless somebody set up an age alert rather than a depth one. Alerting on the age of the oldest message rather than the count is what catches this, and it is the better metric for every queue.