t4mer@notebook

// problem · 24 july 2026 · 1 min

RabbitMQ redelivered a message I thought I had handled

Ack timing, not Laravel tries, decided the retry.

Time wasted: 2 hours

Problem

A consumer performed a side effect (an HTTP call) and then crashed. The broker redelivered. The side effect happened twice.

Environment

RabbitMQ PHP consumer

Symptoms

Duplicate downstream requests. Consumer logs showed the handler starting twice for the same payload. I had not configured Laravel-style tries.

Expected

One downstream request per logical message.

Investigation

Looked at ack timing. Asked whether the handler was idempotent. Checked dead-letter configuration (there wasn’t a useful one).

Things I tried

Catching the exception and not rethrowing - which acked a failure. Prefetch tweaks. Neither fixed duplicates.

Root cause

The message was acknowledged after the side effect in the happy path, but a crash before ack meant RabbitMQ correctly redelivered. The handler was not idempotent.

Solution

Made the handler idempotent using a processed-message key. Ack after the side effect is recorded as complete. Failures go to a dead-letter queue instead of infinite requeue.

Why it worked

Redelivery is a broker feature. Idempotency is your feature. They are not Laravel retry counts.

Lesson

If the side effect is not idempotent, you do not have a retry strategy. You have a duplicate-risk strategy.

Found something wrong?

These notes can be incomplete, or wrong in a different environment. Suggest a correction on GitHub or email me at me@t4mer.net.

// related