Agent Wranglers

Automation and agents Required

Send each message once

Give every automated message a deduplication key, and send through a queue that skips a key it has already sent.

How to do it

Retries, double clicks and crashed workers all send the same receipt twice. Build the key from the event, the template and the recipient, such as order-1042:shipped:ada@example.org. Store it with a unique constraint when the message is queued. Queue the message in the same database transaction as the change that causes it, as the outbox rule describes. Pass the key on as an idempotency key when your sending service accepts one.

Example

const dedupeKey = `order-${order.id}:shipped:${order.email}`;
await db.query(
  'INSERT INTO outbox (dedupe_key, template, recipient) VALUES ($1, $2, $3) ON CONFLICT (dedupe_key) DO NOTHING',
  [dedupeKey, 'order-shipped', order.email],
);
dedupe_key = f"order-{order.id}:shipped:{order.email}"
db.execute(
    "INSERT INTO outbox (dedupe_key, template, recipient) VALUES (%s, %s, %s) ON CONFLICT (dedupe_key) DO NOTHING",
    (dedupe_key, "order-shipped", order.email),
)

How to check

Trigger the same order event twice, and kill the worker once in the middle of a send. The test recipient gets exactly one message.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers email playbook: https://agentwranglers.se/playbook/email/automation-and-agents/send-once.