Acumatica · Acumatica

Acumatica Business Events Dead-Letter Queue

Acumatica Business Events Dead-Letter Queue is the work that turns a collection of business systems into a coherent operation.

John Kihiu12 min read

There's no dead-letter queue in Business Events, because there's no queue at all — a business event fires a subscriber once, synchronously. A dead-letter queue only exists if you build the outbound queue it belongs to, which is the same queue table used for retry, with one more state added: Failed.

A DLQ is just a status value, until it isn't

The simplest version is exactly what it sounds like: an event that's exhausted its retry attempts (see the retry article) gets its status set to Failed instead of being retried again, and a saved filter on the queue screen shows everything in that state. This is enough for low volume — someone checks the filter periodically, reads the last error, fixes whatever's wrong, and manually flips the row back to Pending to force a reattempt.

SQL · DLQ VIEW
SELECT RefNbr, EventType, Attempts, LastError, LastAttemptOn
FROM OutboundEventQueue
WHERE Status = 'Failed'
ORDER BY LastAttemptOn DESC;

When a table and a filter stop being enough

The manual-review approach breaks down once volume grows past what one person glancing at a grid can keep up with, or once failures need to trigger anything automated (an alert, an escalation, a retry with different parameters). At that point it's usually less work to push the failed event onto a real dead-letter queue — an Azure Service Bus dead-letter sub-queue or an SQS DLQ — than to keep extending a homegrown table with features a managed queue already has.

Letting the cloud queue own DLQ semantics

If the outbound processor is already pushing to Service Bus or SQS instead of calling an HTTP endpoint directly, the dead-letter behavior comes for free: Service Bus moves a message to its dead-letter sub-queue after MaxDeliveryCount is exceeded, SQS does the same with a redrive policy pointing at a separate DLQ. In that setup, the Acumatica-side table doesn't need its own Failed state at all — it just needs to record that the message was handed off, and the cloud queue's dead-letter tooling (and whatever alerting you've wired to it) takes over from there.

Decide who's watching the DLQ before you build it

A dead-letter queue that nobody looks at is a slow leak of unprocessed business events. Before adding one, decide whether it's a person checking a filtered grid weekly, or an alert wired to queue depth — either is fine, but "we'll build it and figure out monitoring later" is how a DLQ becomes a place events go to be forgotten.

Reprocessing without duplicating

Manually replaying a dead-lettered event only works safely if the same idempotency key from the original attempt travels with the replay — otherwise fixing the downstream issue and reprocessing produces a second copy of whatever the first, failed attempt partially created. This is the same idempotency discipline covered in the retry article, applied one more time at the point of manual intervention.

Wrapping up

A dead-letter queue for Business Events is either a status column and a saved filter, or a real managed queue's dead-letter feature — the right choice depends entirely on volume and who needs to act on failures, not on anything Acumatica provides natively.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.