Portfolio ©2026Loading experience
Design.Engineer.Ship.
Laravel × React × WebGL000
twogoodson ©
← All notes

Laravel queues that don't wake you up at 3am

Idempotent jobs, sane retries and the Horizon settings I now copy into every project.

Written by

TubagusFull Stack Developer

Published

Reading

6 min

Queues are where good intentions go to fail quietly. A job that works on your machine can still retry forty times in production and email a customer forty times.

Make every job idempotent

Assume every job runs twice. Store a key for the side effect and check it before acting:

if (Payment::where('reference', $this->reference)->exists()) {
    return;
}

Retry on purpose

  • Set $tries and $backoff on the job, not globally.
  • Use retryUntil() for anything that talks to a flaky third party.
  • Call $this->fail() when retrying cannot help.

Separate the queues

Mail, webhooks and heavy reports never share a queue. One slow PDF export should not delay a password reset.

Watch it

Horizon's failed-jobs page is not monitoring. Alert on queue wait time instead — it is the first number to move when something is wrong.

Written by

Tubagus

Full Stack Developer

Share this note

Next note

What a year of Laravel Octane in production taught me→