Lesson 16 · Senior NATS practice
Poison messages, DLQ design, and safer JetStream failure handling
How to reason about redelivery, poison messages, no-DLQ reality, and what a cleaner failure-handling design would look like in this repo.
Your win: explain the repo’s current Ack-only failure model honestly, then describe what a safer poison-message and DLQ strategy would look like without pretending JetStream already gives it to us here.
Why this page matters more than it looks
Earlier lessons taught the mechanics honestly: success acks, retryable failure waits for redelivery, and poison or unparseable messages are ack-dropped. That is already better than hand-wavy reliability talk. But senior understanding goes one step further: it turns that mechanical description into design judgment.
Once you do that, new questions appear. What should happen when a message is permanently bad? When should the system retry in place? When should it preserve failure evidence somewhere safer? What is lost when a poison message is simply acknowledged away? Those are the questions this page is here to train.
What a DLQ actually buys you
A DLQ is not just a storage bucket for bad messages. Its real job is to preserve the failed event, preserve the failure context, and still let the main flow keep moving. That is why the DLQ conversation is really a system-behavior conversation, not just a storage conversation.
The strongest senior answer here is honest: JetStream supports richer ack semantics than the repo uses today, and a future DLQ design could make failure handling more explicit, observable, and recoverable. The important thing is not to pretend that future design already exists in the current system.
Ack semantics with a design lens
Revisit the JetStream model deep dive and compare its richer ack options with the repo’s simpler current policy.
Check yourself (from memory)
Q1. What is the most senior purpose of a DLQ in this context?
Sources. JetStream model deep dive; repo NATS map.