All articles
Operations

WhatsApp Duplicate Messages: Why Sent Twice (India 2026)

Customers getting the same WhatsApp API message twice? It is usually a retry or double trigger with no dedupe. Find the cause and fix it with idempotency keys.

RichAutomate Editorial
14 min read 0 views
WhatsApp Duplicate Messages: Why Sent Twice (India 2026)

Customers get the same WhatsApp Business API message twice when one business event is turned into two send requests — usually a retry after a timeout, a webhook processed twice, or two automations firing on one trigger. The fix is idempotency: give every event a unique key, store it before you call the API, and refuse to send anything whose key already exists.

Duplicates are one of the most common complaints Indian teams raise after going live on the API. A customer forwards a screenshot showing "Your order has been shipped" twice, a sale broadcast lands two times in a row, or an OTP arrives in pairs and the customer is no longer sure which one is valid. Each copy is billed, each copy chips away at trust, and repeated identical messages are exactly the kind of experience that makes people tap Block. This guide walks through where duplicates really come from, how to measure them, and a 30-day plan to get them to zero.

Why duplicates are almost never Meta's fault

When you call the Cloud API send endpoint, Meta accepts the request and returns a message id, the wamid. One accepted request produces one message. Meta does not normally deliver a single accepted request twice to the handset. So when a customer sees two identical messages, the useful assumption is that your system — or something connected to it — made two requests.

That is good news, because it means the problem is fixable in your own code and configuration. The hard part is that duplicates tend to come from the edges: network timeouts, retry policies, integrations nobody remembers switching on, and webhooks that arrive more than once. Meta may retry webhook deliveries when your endpoint responds slowly or with an error, and many queue systems retry failed jobs automatically. Each of these is sensible on its own. Together, without a dedupe layer, they multiply sends.

The seven causes, from most to least common

1. Webhook redelivery processed twice

Your webhook receives an inbound message and triggers an auto-reply. If the endpoint took too long to answer, Meta may deliver the same event again. If you do not check whether you have already processed that inbound message id, the auto-reply goes out twice. This is the single most frequent cause we see in chatbot setups, and the engineering patterns to avoid it are covered in our WhatsApp webhook reliability engineering guide.

2. Client retry after a timeout

Your server calls the send API, the request succeeds at Meta, but the response is slow and your HTTP client times out at, say, 10 seconds. Your code treats it as a failure and retries. Meta now has two valid requests. Without an idempotency key on your side there is no way to tell that the first one worked.

3. Double-click and double-submit

An agent clicks Send in a shared inbox and the button does not disable immediately. A website lead form posts twice on a slow mobile connection in a tier-2 city. A staff member refreshes the page that confirmed a broadcast. Each of these creates a genuine second request.

4. Campaign re-run or overlapping audience lists

A campaign stalls, someone clicks Run again, and the contacts who already received it get it a second time. Or a Diwali offer goes to "All customers" and "Mumbai customers" as two separate campaigns on the same afternoon. If a campaign ever looks stuck, read our note on WhatsApp campaigns stuck in queued or processing before pressing Run a second time.

5. Two automations on one event

A keyword trigger for "price" and a separate welcome flow for new contacts both match the first inbound message "price?". Both fire. The customer receives two different replies, or two copies of the same one if both nodes use the same template.

6. CRM or Shopify integration plus your BSP both sending

The order-confirmation message is configured in a Shopify WhatsApp app and also in your BSP's order automation. Or your CRM sends payment reminders through its own connector while your team built the same reminder on the platform. Two systems, one event, two messages.

7. Queue worker retry after partial success

A job sends the message, then fails on the next step — writing to the database, updating the CRM, broadcasting a status event. The queue marks the whole job as failed and retries it, and the retry sends again. This one is subtle because the logs show a failure, not a duplicate.

Symptom to cause to fix

Use the pattern the customer describes to narrow the cause quickly.

What you seeLikely causeFix
Auto-reply arrives twice, seconds apartWebhook redelivered and processed twiceDedupe inbound by message id; respond 200 fast, process async
Two copies with different wamids, a few seconds apartClient retry after timeoutIdempotency key per event; check before retry
Duplicates only on agent or form sendsDouble-click or double-submitDisable button on click; server-side unique key
Whole segment got the broadcast twice, minutes or hours apartCampaign re-run or overlapping listsExclude already-sent contacts; dedupe audience before launch
Two different replies to one inbound messageTwo automations or triggers matchedTrigger priority and one active flow per contact
Order message twice, one in a different formatStore app and BSP both sendingPick one sender per event; disable the other
Duplicate appears only when a job shows as failedWorker retry after partial successRecord send result before later steps; skip send on retry

What duplicates actually cost

Every accepted request is billed as a message, so a duplicate costs exactly what the original did. On RichAutomate there is no setup fee and no monthly fee; you pay only for usage. On Client Pay the platform fee is ₹0.10 per message and Meta bills its own message charges to you directly. On SaaS Pay it is ₹1.20 per marketing message and ₹0.30 per utility message, all-inclusive. The figures below are illustrative volumes and duplicate rates, not measured averages.

Scenario (illustrative)DuplicatesSaaS Pay extraClient Pay extra
Festive broadcast, 50,000 marketing messages, 3% duplicated1,500₹1,800₹150 platform fee + Meta's charge for 1,500 messages
D2C brand, 2,00,000 utility order updates a month, 2% duplicated4,000₹1,200 a month₹400 platform fee + Meta's charge
Clinic reminders, 20,000 utility messages a month, 5% duplicated1,000₹300 a month₹100 platform fee + Meta's charge

The direct rupee cost is rarely the biggest problem. The larger cost is the customers who block the number after the second identical promotion, and the support tickets asking which OTP or payment link is real. For the full cost model behind these rates, see our breakdown of WhatsApp Business API cost in India.

Quality rating and block risk

Meta does not publish a rule that says "N duplicates lowers your rating". What is known is that quality rating is influenced by how recipients react, including blocks and spam reports, and that messaging limits can be affected when quality drops. A customer who receives the same promotion twice in a minute is more likely to block than one who receives it once. Duplicated marketing messages are therefore a real, if unquantified, risk to your number.

Stop overpaying on WhatsApp

Get a 1-minute BSP audit on WhatsApp

Drop your WhatsApp number — we line-item your current invoice against Meta India rates in under 60 seconds. India-hosted, DPDP-compliant.

DPDP-compliant · India-hosted · 1-min reply

Be careful with anyone who promises that duplicates, or any bulk sending pattern, carry "no ban risk". No provider controls Meta's enforcement. The only dependable protection is to send each message once, to people who opted in, with content they expect. If you are also seeing sends rejected rather than duplicated, our list of WhatsApp Business API error codes decoded will help separate throttling and policy errors from dedupe problems.

The idempotency and dedupe checklist

These controls cover all seven causes above. Most teams need four or five of them, not all at once.

  • One unique key per business event. Build it from what the event is, not when it ran: order_shipped:ORD-48213, otp:+9198XXXXXX12:session-77, campaign:412:contact:9031. A retry of the same event produces the same key.
  • Enforce the key with a database unique constraint. Insert the key into an outbound-events table before calling the API. If the insert fails on the constraint, the event was already handled — do not send.
  • Store the wamid against the key. When Meta returns the message id, save it. On any retry, a stored wamid means "already sent", even if the original job later failed.
  • Deduplicate inbound webhooks by message id. Keep processed inbound ids for at least a day. If an id is already present, acknowledge the webhook and stop.
  • Acknowledge webhooks fast. Return 200 immediately and do the work on a queue, so slow processing does not invite redelivery.
  • Lock per contact plus event. A short lock (for example 30 to 60 seconds in Redis) on contact:event stops two workers or two triggers from sending the same thing concurrently.
  • Separate the send from the side effects. Mark the send complete first; CRM updates and notifications run as their own retryable jobs that never call the send API.
  • Disable buttons and forms on submit, and still rely on the server-side key, because the browser cannot be trusted to prevent a second request.
  • Exclude already-sent contacts on any campaign re-run, and deduplicate phone numbers in the audience after normalising to E.164 format, so 9876543210 and +91 98765 43210 are one contact.
  • One owner per event type. Write down which system sends each message — store app, CRM, or WhatsApp platform — and switch off the others.

How to find the duplicates you already sent

You cannot fix what you have not measured. The query is conceptually simple: find the same recipient receiving the same content more than once within a short window.

  1. Pick a window. Ten minutes catches retries, double-clicks and double triggers. A few hours catches campaign re-runs and overlapping lists.
  2. Group outbound messages by recipient number and by template name or body text, restricted to that window.
  3. Keep groups with more than one row. Each extra row is a duplicate; the sum is your duplicate count, and dividing by total sends gives the duplicate rate.
  4. Look at what the pairs share. Same campaign id means a re-run. Same automation id means a double trigger. Two different sources means an integration overlap. Gaps of exactly your HTTP timeout point to client retries.
  5. Trace who created each send. An audit trail that records the user, automation or API key behind every message turns this from guesswork into a five-minute check — see our guide to a WhatsApp API audit log that shows who sent what.

Be careful not to count legitimate repeats. A payment reminder sent on day 1 and day 3 is intentional; two identical ones in the same minute are not. Tune the window to your business before you report a number.

Duplicate prevention by cause

CausePrimary controlBackup control
Webhook redeliveryInbound message id dedupeFast 200 response, async processing
Client retry after timeoutUnique event key with DB constraintStored wamid checked before retry
Double-click or form resubmitServer-side unique keyDisabled button on submit
Campaign re-run or overlapExclude already-sent contactsNormalised audience dedupe
Two automations on one eventTrigger priority, one active flow per contactPer contact plus event lock
Integration plus BSP both sendingSingle owner per event typeShared event key across systems
Worker retry after partial successRecord send before side effectsStored wamid means skip send

A 30-day plan to reach zero duplicates

Days 1 to 7: measure and stop the obvious

  • Run the duplicate query over the last 30 days and record the baseline rate, split by marketing and utility.
  • List every system that can send a WhatsApp message on your number: platform automations, store apps, CRM connectors, custom scripts.
  • Switch off any second sender for the same event. This alone often removes the largest share.
  • Stop re-running stalled campaigns until you can exclude contacts who already received them.

Days 8 to 15: fix webhooks and automations

  • Add inbound message id dedupe and make the webhook respond immediately.
  • Review keyword triggers and flows for overlaps; set priority so only one fires per inbound message.
  • Add a short per contact plus event lock around auto-replies.

Days 16 to 23: make outbound sends idempotent

  • Create the outbound-events table with a unique key column and a wamid column.
  • Route every custom send through it: insert key, send, store wamid.
  • Split send jobs from side-effect jobs so a CRM failure never triggers a resend.
  • Disable Send buttons and form submits on click.

Days 24 to 30: verify and monitor

  • Re-run the duplicate query and compare against the baseline.
  • Schedule it daily with an alert when the rate goes above a threshold you choose, for example 0.5%.
  • Test deliberately: force a timeout, replay a webhook, double-click a button, and confirm only one message goes out each time.
  • Write the "one owner per event" list into your runbook so the next integration does not reintroduce the problem.

The short version

A customer receiving the same WhatsApp message twice is a sign that one event became two requests. Find the pattern with a same-contact, same-content, short-window query. Remove duplicate senders first, then dedupe inbound webhooks by message id, then make outbound sends idempotent with a unique key and a stored wamid. Every duplicate is billed and every duplicate nudges a customer toward Block, so this work pays for itself quickly.

If you want usage-only pricing with ₹0 setup and ₹0 monthly fees while you clean this up, you can create a RichAutomate account and route your sends through one place.

Ready to ship this?

Get the full migration playbook on WhatsApp

A founder-led 1-minute reply with the migration steps, template approval timeline, and a 14-day pilot offer. DPDP-compliant. India-hosted. No spam.

DPDP-compliant · India-hosted · 1-min reply
Tagged
WhatsApp Business APIDuplicate MessagesIdempotencyWebhooksWhatsApp OperationsIndia 2026
Written by
RichAutomate Editorial
Editorial team at RichAutomate. We build the WhatsApp Business automation platform Indian D2C brands, fintechs, and agencies use to ship campaigns and flows on the official Meta Cloud API.
FAQ

Frequently asked questions

Why is my WhatsApp Business API sending the same message twice?
Almost always because one business event was turned into two send requests. The common causes are a webhook processed twice without deduplication on the message id, a client or queue worker retrying after a timeout when the first send had already succeeded, a double-clicked button, overlapping campaign audiences, or two automations reacting to the same trigger. Meta rarely sends a single API request twice; the duplicate is created on your side.
Does Meta charge for duplicate WhatsApp messages?
Yes. Meta treats every accepted send request as a separate message, so a duplicate is billed like any other message of that category. On RichAutomate SaaS Pay that means an extra ₹1.20 per duplicated marketing message or ₹0.30 per duplicated utility message; on Client Pay it is an extra ₹0.10 platform fee plus whatever Meta bills you directly for that message.
How do I stop duplicate WhatsApp messages permanently?
Make every send idempotent. Give each business event (order shipped, OTP requested, campaign row) a unique key, store it with a database unique constraint before calling the API, store the wamid Meta returns, deduplicate inbound webhooks by message id, and take a short lock per contact plus event so two workers cannot send the same thing at the same time.
Can duplicate messages hurt my WhatsApp quality rating?
They can contribute to it. Repeated identical messages look like spam to the person receiving them, which may increase blocks and reports, and Meta may factor those signals into quality rating and messaging limits. No provider can promise a duplicate will never affect your number, so the safe approach is to remove duplicates at the source rather than hope they go unnoticed.
How can I find out how many duplicates I have already sent?
Query your outbound message log for the same recipient and the same body or template sent more than once within a short window, for example ten minutes. Group by contact and message content, count rows above one, and then check whether those rows share one trigger, one campaign, or one retry. Your audit log should show which user, automation or API key created each send.
RichAutomate · WhatsApp BSP for India 2026

Ship WhatsApp campaigns + flows on a transparent, compliance-ready BSP.

₹0 platform fee. DPDP audit log included. Visual flow builder. Multi-tenant from day one.

Start free trial
Want this for your brand?

Get a free 24-hour BSP audit

Send us your last invoice. We line-item it against Meta's published rates and benchmark against three alternatives.

Limited Spots Available

Get a Free
Automation Audit

Stop leaving revenue on the table. Get a custom roadmap to automate your growth.

Secure & Confidential