External Event Consumption in Salesforce — Retries & Dead-Letter Concepts
When Salesforce consumes external events (for example, Platform Events published by another system), your integration logic must be resilient. Failures will happen — networks time out, APIs throttle, or payloads contain invalid data.
A robust event consumer does two key things:
-
It retries transient errors safely without looping forever.
-
It dead-letters unrecoverable events so nothing gets silently dropped.
The goal is to never lose visibility, avoid duplication, and keep side effects idempotent.
? 1. Classify Failures
Before you write retry logic, classify failures as either retryable or terminal.
Retryable failures include:
-
Network timeouts
-
5xx (server) errors
-
Lock contention (
UNABLE_TO_LOCK_ROW)
✅ Action: Retry with exponential backoff and a maximum attempt cap.
Terminal failures include:
-
Validation or business rule errors
-
Missing reference data
-
Schema or data format mismatches
? Action: Dead-letter the event with full context for later investigation.
⚙️ 2. Prioritize Idempotency
External event buses operate on an “at-least-once delivery” model. That means the same event might arrive multiple times.
To prevent duplicate processing, enforce idempotency using a unique key from the event (e.g., DedupKey__c) and a unique record store (like Idempotency__c.Key__c UNIQUE).
Your logic should:
-
Claim then act — attempt to insert the dedup key first.
-
If the insert succeeds, process the event.
-
If it fails with a duplicate error, safely skip it.
This pattern ensures safe replays and prevents side effects like duplicate invoices or API calls.
? 3. Design a Retry Policy
Retries should be bounded and observable, not infinite loops.
Keep a per-event attempt counter (for example, JobRun__c.Attempt__c or a payload field).
Use:
-
Queueable Apex for asynchronous work.
-
Schedulable Apex for delayed retries (e.g., 1 min, 5 min, 15 min).
Stop after a fixed number of attempts, then send the event to your Dead-Letter Queue (DLQ) for review.
? 4. Build a Dead-Letter Queue (DLQ)
A Dead-Letter Queue is a dedicated custom object (e.g., Dead_Letter__c) where failed events are stored permanently until reviewed.
Include the following fields:
-
DedupKey
-
Payload
-
Error
-
Attempts
-
CorrelationId
-
ReplayId or Timestamp
-
Suggested Fix
Admins can view these records in a list view or dashboard, analyze root causes, and reprocess fixed messages from a Flow or custom button.
This pattern ensures no event disappears — every failure becomes traceable.
? 5. Observability
Reliability means nothing without visibility.
To monitor behavior:
-
Log
AsyncApexJobIDs and attempt counts. -
Capture the last error message and time.
-
Optionally publish a status Platform Event like “EventFailed” or “EventRetried” for alerting and monitoring.
These details allow both developers and admins to understand system health in real time.
? Real-World Example: Code Overview
Scenario
An external billing system publishes Invoice_Event__e (Created/Updated).
Salesforce consumes the event via a Platform Event Trigger.
The trigger enforces idempotency, calls an external API, applies bounded retries with backoff, and moves terminal failures to a Dead-Letter Queue.
Custom Objects Used
Idempotency__c
-
Key__c(Text, External ID, Unique) -
ConsumedAt__c(Datetime)
Dead_Letter__c
-
DedupKey__c(Text) -
EventType__c(Text) -
Payload__c(Long Text) -
Attempts__c(Number) -
LastError__c(Long Text) -
CorrelationId__c(Text) -
FirstSeen__c,LastSeen__c(Datetime)
A) Entry — Platform Event Trigger (Claim Then Enqueue)
? Why This Works
-
Idempotency ensures safe replays — duplicate messages won’t double-process.
-
Bounded retries handle temporary errors without overwhelming dependencies.
-
Dead-lettering captures hard failures for visibility and manual intervention.
-
Queueable + Schedulable gives flexibility for async and delayed processing.
This architecture keeps your external integrations reliable, observable, and maintainable

? Final Thoughts
Reliable external event consumption in Salesforce comes down to three principles:
-
Idempotent consumers — process each event exactly once.
-
Smart retry policies — backoff and limit attempts.
-
Dead-letter visibility — store and review failures safely.
Treat every failure as either retryable (retry with backoff) or terminal (send to DLQ).
By persisting detailed diagnostic context, operations teams can confidently fix issues and re-enqueue events — ensuring no data loss and no infinite loops.
This pattern keeps your event-driven pipelines resilient, predictable, and production-grade.
