Building a webhook consumer in Node.js to catch routing/queue/statistics events. The endpoint is up, but GC is hitting it with a 502 Bad Gateway from our load balancer occasionally. The platform retries three times with exponential backoff, which is fine, but we need a dead letter queue for anything that fails after those retries. The docs don’t mention a native DLQ hook for webhooks, so I’m trying to implement it on the consumer side.
The issue is distinguishing between a transient 502 and a permanent failure. If I return 500, GC retries. If I return 200, it stops. I need to return 200 to acknowledge receipt, then push the payload to an SQS DLQ if the downstream processing fails. But the webhook payload includes a webhook_id and event_id. Is there a way to query the webhook delivery status via the API to confirm if GC considers it ‘delivered’?
Here’s the current handler:
import { Request, Response } from 'express';
app.post('/webhooks/gc-stats', async (req: Request, res: Response) => {
const payload = req.body;
try {
await processStats(payload);
res.status(200).send('OK');
} catch (err) {
// Push to DLQ here
await dlq.sendMessage(payload);
// Return 200 to stop GC retries, but how do I log this as a 'failed delivery'?
res.status(200).send('OK');
}
});
The processStats function calls our internal API, which sometimes throws a 502. I want to capture these. The problem is that by returning 200, I’m telling GC it’s good, so I can’t use the native retry logic for my DLQ. I’m thinking of returning 500 for my own retries, but that conflicts with GC’s retry logic. Is there a standard pattern for this? Or should I just ignore the 502s and let them fail silently? The SDK doesn’t have a markWebhookAsFailed method. I’m stuck on the error handling logic.