Webhook Reliability
Three rules for reliable WhatsApp webhook handling — respond 200 immediately, deduplicate deliveries by message ID, and don't assume messages arrive in order.
On this page
Meta's webhook delivery system is designed for reliability — which means it retries failed deliveries. Your server must follow three rules to handle this correctly.
Rule 1 — Send 200 immediately, process after#
Meta expects a 200 response within a few seconds. If it doesn't get one, it retries the same
event — which means your bot processes the same message twice.
app.post('/webhook', (req, res) => {
res.sendStatus(200); // ← FIRST — before any logic
const message = changes.messages[0];
// process here, after 200 is sent
});| Response | What Meta does |
|---|---|
| 200 immediately | Never retries — done |
| No response / timeout | Retries for up to 24 hours |
| 500 error | Retries |
Rule 2 — Deduplicate by message ID#
Because Meta retries, the same message can arrive twice with the same id. Store seen IDs and
skip duplicates:
const seen = new Set(); // use a database in production
if (seen.has(message.id)) return; // already processed
seen.add(message.id);
// now process safelyRule 3 — Don't trust order#
If a customer sends "Hi", "How are you?", "Hello?" quickly, Meta does not guarantee they arrive
in order. If order matters, sort by the message timestamp:
const timestamp = parseInt(message.timestamp); // unix timestampFrequently asked#
Why is my bot replying twice to the same message?
Your server is not responding 200 fast enough, or it's doing slow work before sending 200. Meta retries and your handler runs twice. Fix: send 200 first, then process.
Do I need to worry about duplicate messages on a test setup?
Not much — duplicates are rare in testing. But in production with real traffic, always
deduplicate by message.id.
Gotchas & common mistakes#
Was this page helpful?
Still stuck? Open a support ticket and our team will help.