Webhook timeout: causes, diagnosis, and fixes
A webhook timeout occurs when the sender does not receive a response within its delivery window. The request may still have reached your application and may even complete after the sender starts a retry.
Why webhook handlers time out
- Database queries, external API calls, email, or file processing run before acknowledgment.
- The application is cold-starting, overloaded, or waiting for a saturated connection pool.
- DNS, TLS, proxy, or load-balancer delays consume the delivery window.
- A dependency call has no shorter timeout of its own.
- The handler deadlocks or waits indefinitely on a queue or lock.
Diagnose the slow stage
- Compare the provider delivery duration with ingress, route-start, acknowledgment, and job-completion timestamps.
- Confirm whether the request reached the application before the provider timed out.
- Measure signature verification, parsing, database writes, queue publication, and dependency calls separately.
- Check infrastructure metrics for cold starts, CPU saturation, connection exhaustion, and network errors.
- Look for retries of the same event ID before changing the handler.
Acknowledge, then process
javascript
app.post('/webhooks/provider', rawBodyMiddleware, async (req, res) => {
verifySignature(req.rawBody, req.headers);
const event = JSON.parse(req.rawBody);
await persistInboxEvent(event.id, event); // durable, idempotent write
res.sendStatus(200);
// A worker processes the stored event outside this request.
});Prevent duplicate side effects
A timeout creates uncertainty: the sender may retry while the first attempt continues. Store provider event IDs and make writes idempotent so both attempts can be accepted safely.
Verify the fix
- The handler acknowledges within the provider delivery window.
- Slow work continues through a durable queue or inbox record.
- A retry of the same event ID does not repeat the business action.
- Latency metrics show the acknowledgment path separately from total processing time.