---
title: "Send each message once · Agent Wranglers"
url: https://agentwranglers.se/playbook/email/automation-and-agents/send-once
updated: 2026-10-20
licence: "All rights reserved"
---

# Send each message once

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Automation and agents](https://agentwranglers.se/playbook/email/automation-and-agents)
- Rule: Give every automated message a deduplication key, and send through a queue that skips a key it has already sent.
- How: 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](https://agentwranglers.se/playbook/data/transactions-and-concurrency/outbox) describes. Pass the key on as an idempotency key when your sending service accepts one.
- 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.

Example:

```js
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],
);
```

```python
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),
)
```

**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`.

- Previous: [Send calendar invites that update correctly](https://agentwranglers.se/playbook/email/automation-and-agents/calendar-invites)
- Next: [Add structured data to orders and bookings](https://agentwranglers.se/playbook/email/automation-and-agents/email-markup)
- [Automation and agents](https://agentwranglers.se/playbook/email/automation-and-agents)
