Skip to content
man glossary/webhook-acknowledgement

glossary define webhook-acknowledgement

Name

Webhook Acknowledgement

Answering each WhatsApp webhook with HTTP 200 once it is verified and safely stored, then processing it asynchronously so slow work never looks like a failure.

Synopsis

Webhook ACK, Acknowledge-then-process, Return 200 fast, Webhook acknowledgment

Section

Webhooks & events

Level

practitioner

▍

Reviewed

Behind the 200: can the workers keep up?

16× slow motionService time S = 120 ms per job on average · 6 workers

Queue diagram: 2 events waiting, 5 of 6 workers busy, 7 done, 1 dead-lettered.

Backlog
2.1
events waiting on average
Throughput
40/s
39.2/s done · 0.8/s dead-lettered
Average wait
52 ms
52% of events wait at all
Utilisation ρ
0.8
≈ 4.8 of 6 busy
40 events/s
6

ρ = λ × S ÷ c = 40/s × 120 ms ÷ 6 = 0.8

ρ = 0.8 < 1: the workers keep up, so the queue drains between bursts and waits stay short.
Each event has already been verified, stored and answered with 200; here background workers drain the queue. Raise the arrival rate to see the backlog grow while Meta still gets instant acknowledgements.

Utilisation is below 1: the workers keep up.

Description

What is webhook acknowledgement?

Webhook acknowledgement is your side of the delivery contract with Meta. For every POST to your webhook endpoint, Meta expects an HTTP 200 status. Anything else — a 4xx, a 5xx, a redirect, a dropped connection or a request that simply takes too long — counts as a failed delivery, and Meta retries it with decreasing frequency for up to seven days. The acknowledgement means "I have safely received this", not "I have finished handling it".

That leads to the acknowledge-then-process pattern. The request handler does only three cheap things: verify the X-Hub-Signature-256 signature over the raw body, write the payload to something durable (a queue, a log or a table), and return 200. Everything slow — CRM updates, chatbot or LLM calls, media downloads, database joins — happens afterwards in background workers. The handler's response time then stays flat however heavy the downstream work becomes.

Storing before answering matters because Meta offers no API to fetch historical webhook data. Once you have returned 200, Meta considers the event delivered and will not send it again, so an event acknowledged but not yet persisted is lost if the process crashes. Acknowledgement is also different from the webhook retry policy: the retry policy is what Meta does when your acknowledgement does not arrive, while acknowledgement is how you make retries rare in the first place.

Key takeaways

  • Webhook acknowledgement means answering every WhatsApp webhook POST with HTTP 200 once it is verified and durably stored.
  • Any other outcome — an error status, a redirect, a timeout or a dropped connection — makes Meta retry for up to seven days.
  • Verify the signature, persist the raw payload, return 200, and leave every slow task to background workers.
  • Meta has no API to fetch past webhooks, so an event acknowledged before it is stored is lost for good.
  • Return 503 only when you could not store the event; answer 200 for fields you ignore and events you cannot parse.

Mechanics

How does webhook acknowledgement work?

  1. step 1 — Read the raw body

    Capture the request bytes exactly as received. The signature is computed over them, and you will store them unchanged.

  2. step 2 — Verify the signature

    Recompute the HMAC-SHA256 of the raw body with your app secret and compare it with X-Hub-Signature-256 in constant time. Reject mismatches with 401 or 403.

  3. step 3 — Persist durably

    Write the payload to a durable message queue or an append-only table before answering. This is the only copy you will ever have.

  4. step 4 — Return 200 immediately

    Send 200 with an empty or minimal body. Do not wait for processing, and do not vary the status by event type — answer 200 for fields you ignore too.

  5. step 5 — Process asynchronously

    Workers read from the queue, apply webhook deduplication, and run side effects. Failures are retried by your own queue and parked in a dead-letter queue — never pushed back onto Meta.

  6. step 6 — Watch the acknowledgement path

    Alert on p99 response time and on the share of non-200 responses. Either creeping up is the early warning of a retry storm.

Usage

Webhook acknowledgement in code

import crypto from "node:crypto";
import express from "express";
const app = express();
// Keep the raw bytes and allow Meta's 3 MB maximum payload.
app.use(express.raw({ type: "application/json", limit: "4mb" }));
app.post("/webhooks/whatsapp", async (req, res) => {
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.APP_SECRET)
.update(req.body)
.digest("hex");
const given = req.get("X-Hub-Signature-256") ?? "";
if (given.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected))) {
return res.sendStatus(401);
}
try {
await inbox.insert({ raw: req.body.toString("utf8"), receivedAt: new Date() });
} catch (err) {
return res.sendStatus(503); // not stored, so let Meta retry
}
return res.sendStatus(200); // stored: acknowledge, process later
});

Verify, persist, acknowledge. A failed write returns 503 on purpose so Meta's retry keeps the event alive.

Properties

Webhook acknowledgement: key facts and limits

Success response
HTTP 200
Anything else
Treated as failure and retried
Retry window
Decreasing frequency, up to 7 days
Maximum payload
3 MB
Updates per request
Up to 1,000 (batching not guaranteed)
Published timeout
None — answer in milliseconds, not seconds
History API
None: store events before acknowledging

Caveats

Common mistakes with webhook acknowledgement

  • Doing the work before answering

    Database joins, CRM calls and LLM replies inside the request make response time depend on other systems. Move them to workers and keep the handler to verify, store, answer.

  • Acknowledging before storing

    Returning 200 and then enqueuing in memory loses events on every crash or deploy, and Meta will not resend them. Persist first, then answer.

  • Answering 202 or 204

    Meta's documentation asks for 200 specifically; no other value among the HTTP status codes is documented as success, and some frameworks default to 204 for empty responses. Set the status explicitly rather than relying on another 2xx being accepted.

  • Turning business errors into HTTP errors

    Returning 404 for an unknown customer or 422 for an event you cannot parse makes Meta retry it for days. Store it, return 200, and handle the problem in your own dead-letter queue.

Why it matters

Why does webhook acknowledgement matter?

The acknowledgement decides whether the inbound pipeline flows or snowballs. A handler that calls a CRM before answering is fast on a quiet afternoon and fails during a broadcast's status wave: responses slow down, Meta treats them as failures, retries pile on top of new traffic and duplicates multiply. Acknowledging in milliseconds keeps Meta's view of your endpoint healthy, isolates customer-facing replies from slow internal systems and turns every downstream outage into a backlog you drain, rather than a retry storm you fight.

Example

Example: A results-morning status wave in Hyderabad

A Hyderabad diagnostics chain sends 60,000 "report ready" utility templates at 7 am. Each message can produce sent, delivered and read statuses, so status webhooks peak for the next hour. Its old handler updated the patient record and called the CRM before answering, often taking over two seconds; deliveries timed out, Meta retried, and the same statuses were processed three or four times. After moving to acknowledge-then-process — verify, insert into a queue table, return 200 — the handler answers in about 15 ms, the queue absorbs the peak, and workers catch up within minutes (figures illustrative).

Questions

Webhook Acknowledgement FAQs

What should my webhook return when the signature check fails?
Return 401 or 403. A genuine Meta request only fails the check if your app secret is wrong, so alert on a sudden rise — otherwise you will reject real events for as long as Meta keeps retrying them.
What happens if processing fails after I returned 200?
Meta will not resend it; to Meta the event was delivered. Your own queue must retry the work and park repeated failures in a dead-letter queue for inspection.
How fast does a WhatsApp webhook acknowledgement need to be?
Meta does not publish a timeout, so answer in milliseconds. Verify-store-answer needs no network calls beyond one durable write; treat anything near a second as a warning sign that slow work has crept into the request.
Should I return 202 Accepted because I process the event later?
No, return 200. Meta's documentation asks for a 200 OK on every notification, and the status only means you have safely received the event — not that you have finished processing it.

Notes

Best practices for webhook acknowledgement

  • Give the acknowledgement path its own process or pool, so a busy worker fleet can never slow it down.
  • Set the body-size limit above 3 MB on every proxy and framework in front of the handler.
  • Return 503 only when you genuinely could not store the event — that is the one case where a retry helps.
  • Load-test with a realistic status wave, not a trickle of single messages.
  • If several systems need each event, use webhook fan-out from the queue after the 200 — never inside the request.

See InfiQ pricing

Put Webhook Acknowledgement to work

InfiQ is an official Meta Business Partner. Start a 7-day free trial — no card needed — and see this running on your own number.