THE USEFUL ANSWER
Duplicate prevention needs an identity for the intended action and a record of its outcome. A delay or a check of the last message alone cannot reliably distinguish a retry from a new task.
- Separate repeated events from genuinely new eligible actions.
- Treat an unknown delivery outcome differently from a confirmed failure.
- Use one active owner for each send workflow.
- Identify
Relationship + event + workflow step
- Claim
One worker owns the action
- Execute
Attempt the permitted send
- Reconcile
Record confirmed or uncertain outcome
Diagnose the kind of duplicate
Two similar messages can have different causes. The same event may arrive twice. Two tools may react independently to one event. An operator may send a reply while a delayed automation is waiting. Or a request may time out after the message was accepted, leading to a retry.
Start by comparing event references, intended recipients, workflow steps and outcomes. Similar wording alone does not tell you whether the underlying action was duplicated.
Keep the workflow plan beside the investigation. It should identify which system owns the action and what other senders can be active at the same time.
Identify the intended action
A useful action identity combines the scope that makes the operation unique. Conceptually, that might include the relationship reference, the source event and the specific workflow step. Use stable internal identifiers rather than names that can change.
A key that is too broad can suppress legitimate future actions. A key that changes on every retry cannot prevent repetition. Define how long the same event should be recognized and what creates a genuinely new eligible action.
Stripe’s idempotency documentation provides an implementation example of associating repeat requests with a key. That is an analogy for this design discussion, not evidence that OnlyFans or a chosen messaging provider exposes the same mechanism or guarantees.
Treat uncertain outcomes as a separate state
| Observed result | What it establishes | Next step to define |
|---|---|---|
| Confirmed success | The system reported acceptance or delivery at its documented stage | Record the reference and avoid a blind repeat |
| Confirmed rejection | The request was rejected under the documented response | Correct the cause before an eligible retry |
| Timeout or lost response | The client does not know the final outcome | Reconcile using supported status evidence |
| Missing local record | Your record is incomplete | Investigate before assuming nothing happened |
A timeout is not proof that no message was sent. Equally, an accepted request may not prove final delivery unless the API documents that meaning. Preserve the distinction in the operator interface.
If the provider offers no reliable reconciliation mechanism, escalate uncertain sends for review and limit the workflow accordingly. Do not advertise an exactly-once guarantee that the underlying system cannot support.
Coordinate automated and human senders
A duplicate guard inside one service does not stop another independent tool from sending an equivalent message. Assign one owner to each event-driven sequence and document any intentional overlap.
For a human reply during a delay, recheck the conversation state before execution. The welcome workflow describes when cancelling the queued greeting may be the appropriate outcome.
During a migration, disable the old trigger before enabling the replacement for the same scope, and review already queued work separately. A switch that stops new triggers may leave existing actions active.
Test the failure paths deliberately
Use a test environment or other supported non-live mode with synthetic recipients. Deliver the same event twice, start two workers if the architecture permits it, interrupt a response and simulate a human action during the queue delay.
Record the expected number of intended sends and the resulting action records. Check that preventing a duplicate does not also block a legitimate later event. Inspect expiry and cancellation as well as successful execution.
A useful test report states the cases, system configuration and observed outcomes. It does not turn a few successful retries into a universal reliability claim.
Keep an operational recovery path
When a duplicate does occur, pause the affected sequence, determine its scope and preserve the relevant event references. Correct the ownership or retry rule before replaying work.
The timing guide covers tasks that become irrelevant while waiting. The goal is not merely to send once; it is to send an eligible, current message through a workflow whose outcome the team can understand.
Sources & editorial notes
Primary references checked on 10 September 2026. Calculations and proposed workflows are our editorial examples, not independently observed provider results.