Dead Lettered Events
Events a consumer gave up on after five inbox attempts
Four dead lettered rows. Two can be replayed and two cannot. Whether replay is possible depends on where the row died, and the difference is not cosmetic: an outbox row still holds its envelope, a consumer inbox row records only that a message failed.
Dead lettered now
4
2 replayable
In the last 7 days
11
9 already cleared
Oldest open
2 days
A KYCUpgraded event
Events published in 24h
1,284,900
0.0003% dead lettered
| Event | Aggregate | Consumer | Attempts | Died in | Replay |
|---|---|---|---|---|---|
| KYCUpgraded evt-2026-8841902 | PTY-0004471 | BE03 Lending | 5 | Outbox | Available |
| OrderShipped evt-2026-8841744 | ORD-KE-100482 | BE07 Notifications | 5 | Outbox | Available |
| SettlementPaid evt-2026-8841203 | SET-2026-07-19-KE-01 | BE04 Marketplace | 5 | Consumer inbox | Not possible |
| PartyCreated evt-2026-8840118 | PTY-0011908 | BE02 Wallet | 5 | Consumer inbox | Not possible |
Five attempts, then it stops. Retrying forever turns one broken consumer into a backlog that starves every other consumer on the bus, so a row that fails five times is parked here for a person to look at.
Dead Lettered Events
Nothing dead lettered
Nothing dead lettered
This is the normal state. 1,284,900 events were published in the last 24 hours and every one was consumed by every subscriber inside its retry budget.
| Events published, 24 hours | 1,284,900 |
| Consumed at least once | 1,284,900 |
| Needed a retry | 412, all succeeded within 5 attempts |
| Dead lettered | 0 |
| Alert threshold | event_dead_letters_total above 0 pages the on-call engineer |
Any number above zero here is an alert, not a queue to work through. A dead letter means a consumer has a bug or a dependency is down, so the right response is usually to fix that and then replay, not to replay repeatedly.
Dead Lettered Events
evt-2026-8841902, KYCUpgraded, outbox
The envelope is still held, so replay is genuinely possible. An outbox row is the message itself, waiting to be published. Putting it back on the bus is a real operation rather than a button that hopes.
| Event | KYCUpgraded |
| Event id | evt-2026-8841902 |
| Aggregate | PTY-0004471, Aline Uwase |
| Published by | BE01 Identity |
| Failing consumer | BE03 Lending |
| Attempts | 5, the maximum |
| First attempt | 17 July 2026 14:24:08 |
| Gave up | 17 July 2026 14:31:44 |
| Last error | Connection refused, lending decision service |
| Envelope held | Yes |
| Replay | Available, under maker-checker |
Envelope
As published, unmodified| event_id | evt-2026-8841902 |
| event_type | identity.kyc.upgraded.v1 |
| aggregate_id | PTY-0004471 |
| occurred_at | 2026-07-17T14:24:02.118Z |
| idempotency_key | kyc-1188-tier2 |
| schema_version | 1 |
| payload | { party_id, from_tier: 1, to_tier: 2, case_id } |
| trace_id | 4c1f88e0-2a58-4de3-8f01-6c5d3b7a9e42 |
Replay is safe because the consumer is idempotent. The idempotency key means that if BE03 did in fact process this before dying, replaying it changes nothing. That is what makes replay a reasonable operation rather than a gamble.
Fix the consumer first. Replaying into a service that is still refusing connections just burns another five attempts. Check that BE03 is healthy, then replay.
Dead Lettered Events
evt-2026-8841203, SettlementPaid, consumer inbox
Replay is not available for this row, and there is no button that would refuse. A consumer inbox row records that a message failed. It does not hold the message. There is no envelope to put back on the bus, so offering replay would be offering something that cannot happen.
| Event | SettlementPaid |
| Event id | evt-2026-8841203 |
| Aggregate | SET-2026-07-19-KE-01 |
| Published by | BE04 Marketplace |
| Failing consumer | BE04 Marketplace, merchant read model |
| Attempts | 5, the maximum |
| Gave up | 19 July 2026 06:14:22 |
| Last error | Deserialisation failed, unexpected field payout_reference |
| Envelope held | No |
| What the inbox holds | The event id, the attempt count and the last error |
| Replay | Not possible from here |
| Where a row dies | What is stored | Replay possible | Why |
|---|---|---|---|
| Outbox, before publish | The full envelope, ready to publish | Yes | The message exists and can be put back on the bus |
| Consumer inbox, after delivery | The event id, attempts and the last error | No | The message was consumed and discarded; only the failure was recorded |
What you actually do with this one. The error says the consumer could not deserialise a field the publisher added, which is a schema evolution problem. Fix the consumer to tolerate the new field, then replay the event from the publisher outbox if the retention window still holds it, or rebuild the read model from the aggregate.
Re-arming this row is a database operation today. There is no supported way to reset a consumer inbox row from this screen, and the screen says so rather than implying otherwise. It needs an engineer with a migration, recorded as a change.
Dead Lettered Events
Re-arming a dead consumer inbox row
This screen cannot do it, and it will not pretend to. Re-arming a dead consumer inbox row is a database operation today. There is no API for it, so there is no button for it. What follows is what actually has to happen, so an operator knows what they are asking for.
| Step | Who does it | What it involves |
|---|---|---|
| 1. Fix the consumer | Platform engineering | The deserialisation failure has to be fixed and deployed first, or the row will just die again |
| 2. Raise a change | Platform engineering | A data change against the inbox table, reviewed and approved like any other production change |
| 3. Reset the attempt count | Platform engineering | Set the row back to zero attempts so the consumer picks it up again |
| 4. Confirm consumption | Platform engineering and the module owner | Check the read model actually caught up |
| 5. Record it | The change process | The change and its approval land in the audit chain like everything else |
| Supported from this screen | No |
| API endpoint for it | None exists at Phase 1 |
| Typical turnaround | Same business day, once the consumer fix is deployed |
| Alternative that is supported | Rebuild the read model from the aggregate |
| Why it is not automated | Resetting a failure record so a consumer retries is easy to get wrong and hard to undo, and the safe alternative already exists |
Naming the gap is the point. A screen that showed a re-arm button which quietly did nothing, or which worked only sometimes, would be worse than one that says plainly what has to happen and who does it.