Skip to content

feat: consume the retry subject instead of parking failures - #16

Merged
bludot merged 1 commit into
mainfrom
feat/consume-retry-subject
Aug 29, 2026
Merged

bludot merged 1 commit into
mainfrom
feat/consume-retry-subject

Conversation

@bludot

@bludot bludot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

feat: consume the retry subject instead of parking failures

The backoff retry middleware republishes a failed message to -retry,
but nothing consumed that subject, so a failure was parked rather than retried
and no alert fired. In production that hid broken user creation for seventeen
days behind a consumer report that looked entirely healthy.

Run a second processor over the retry subject in this same process, so no new
deployment is needed. It gets its own driver: ep takes the durable consumer name
from driver-level config rather than per-subject, so two Consume calls on one
driver would call CreateOrUpdateConsumer with the same durable name and
different filter subjects, and the second would reconfigure the first.

Exhausted retries now go to -dlq rather than back onto the retry
subject. ep acks and drops a message once the counter reaches MaxRetries, so
cycling would make a permanently failing message vanish with no record, which
is the same invisibility in a shorter loop.

The two consumers run under an errgroup so that one returning stops the other.
Consume blocks until its iterator is stopped, so otherwise a dead main consumer
would leave the process alive and apparently healthy.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

The backoff retry middleware republishes a failed message to <subject>-retry,
but nothing consumed that subject, so a failure was parked rather than retried
and no alert fired. In production that hid broken user creation for seventeen
days behind a consumer report that looked entirely healthy.

Run a second processor over the retry subject in this same process, so no new
deployment is needed. It gets its own driver: ep takes the durable consumer name
from driver-level config rather than per-subject, so two Consume calls on one
driver would call CreateOrUpdateConsumer with the same durable name and
different filter subjects, and the second would reconfigure the first.

Exhausted retries now go to <subject>-dlq rather than back onto the retry
subject. ep acks and drops a message once the counter reaches MaxRetries, so
cycling would make a permanently failing message vanish with no record, which
is the same invisibility in a shorter loop.

The two consumers run under an errgroup so that one returning stops the other.
Consume blocks until its iterator is stopped, so otherwise a dead main consumer
would leave the process alive and apparently healthy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bludot
bludot merged commit da0488a into main Aug 29, 2026
2 checks passed
@bludot

bludot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

🎉 This PR is included in version 1.17.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant