Webhook Monitoring: How to Verify Your Integrations Are Working
Webhooks are the connective tissue of modern SaaS — but they fail silently. No error page, no bounce, no user complaint until a critical flow breaks completely. Here's how to know your webhooks are actually delivering.
Every modern SaaS product relies on webhooks. Stripe fires a webhook when a subscription renews. GitHub fires one when a pull request is merged. Your own product probably sends webhooks to customer systems when something important happens. And your monitoring tool — hopefully — sends webhooks to your incident channel when something goes down.
The problem with webhooks is that they're push-based and fire-and-forget. The sender fires the request and moves on. If the receiver is down, if the URL changed, if the payload format was updated and the consumer stopped accepting it — the sender typically doesn't know. The integration breaks silently, sometimes for days before anyone notices.
How webhooks fail silently
There are several ways a webhook integration can stop working without producing an obvious error:
The receiving endpoint goes down
Your webhook receiver is an HTTP endpoint — a URL that accepts POST requests. If that endpoint returns a 500, or times out, or the server it's hosted on goes down, webhooks stop delivering. The sending service may log a delivery failure, but the consumer doesn't know unless someone checks the sender's dashboard. If you're not monitoring the webhook endpoint itself, you won't catch this until a user asks "why didn't we get notified about X?"
The URL changes without updating the sender
Your backend gets refactored. The webhook endpoint moves from /api/webhooks/stripe to /webhooks/stripe. The old URL now returns 404. Stripe is still sending to the old URL. Payments aren't being processed. Nobody knows.
Schema drift
The sending service updates their webhook payload format. A field gets renamed, a new required field is added, an enum value changes. Your consumer breaks because it expects the old format. It may silently discard the payload (if you have a try/catch that swallows errors) or it may start throwing 500s — which the sender logs as failures but doesn't alert you about.
Authentication failures
Many webhooks use a shared secret for verification. The sender signs the payload, the receiver verifies the signature. If the secret gets rotated on either side without updating the other, every webhook silently fails signature verification and gets discarded.
Strategy 1: Monitor the webhook endpoint with HTTP monitoring
The simplest layer of webhook monitoring: treat your webhook receiver URL like any other HTTP endpoint and add an HTTP monitor to it.
The catch is that webhook endpoints accept POST requests, not GET. Most monitoring tools default to GET. You need a monitor that:
- Sends a POST request to your webhook URL
- Optionally includes a test payload in the body
- Checks that the response is 200 (not 404, 500, or timeout)
PingBase HTTP monitors support custom HTTP methods (POST, PUT, etc.) and custom request bodies. You can configure a monitor that sends a POST to your webhook endpoint every minute with a test payload, verifying the endpoint is reachable and returning a healthy response code.
This catches the most common failures: endpoint down, URL changed, server crash. It doesn't verify end-to-end delivery — just that the endpoint is accepting requests.
Strategy 2: Heartbeat monitoring for webhook consumers
For deeper verification, use a heartbeat monitor. The idea: your webhook consumer, after successfully processing a webhook, pings a heartbeat URL. If PingBase stops receiving pings, it alerts you — the consumer stopped processing.
Implementation sketch for a Stripe webhook handler:
// After processing a webhook event successfully
app.post('/webhooks/stripe', async (req, res) => {
const event = stripe.webhooks.constructEvent(
req.body, req.headers['stripe-signature'], secret
);
await handleStripeEvent(event);
// Ping heartbeat to confirm successful processing
await fetch('https://app.pingba.se/ping/your-heartbeat-id');
res.sendStatus(200);
});
Configure the heartbeat monitor in PingBase with an interval that matches how frequently you expect webhooks: if Stripe fires a webhook at least once every hour (subscription renewals, payment attempts, etc.), set the heartbeat interval to 90 minutes. If PingBase doesn't receive a ping within that window, it alerts you — something stopped the consumer from processing.
This approach catches failures that HTTP monitoring misses: the endpoint returns 200 but the processing code throws an error that gets swallowed, the signature verification fails silently, the database write fails after the 200 is sent.
Strategy 3: Monitor your own webhook delivery
If your product sends webhooks to customer systems, you need to monitor delivery from your end too. Key metrics to track:
- Delivery success rate — what percentage of outgoing webhooks receive a 2xx response
- Failed delivery count by destination — which customer endpoints are consistently failing
- Retry queue depth — are retries backing up, indicating a systemic issue?
- Time to first delivery — are webhooks being delivered promptly or is there a queue delay?
PingBase uses exponential backoff retry logic for its own webhook delivery: if a delivery fails, it retries at 1 minute, then 5 minutes, then 30 minutes, then 2 hours. After exhausting retries, the delivery is marked as permanently failed and the customer is notified via alternative channels. Your webhook system should do the same.
Common mistake: alerting on every delivery failure
Don't alert your team every time a single webhook delivery fails. Customer endpoints go down temporarily all the time. Alert when a delivery has failed across all retries — meaning the integration is permanently broken until the customer fixes their endpoint.
Verifying webhook signature validation
Most webhook senders sign their payloads with an HMAC signature. Your receiver should verify this signature on every request. But this verification code is often undertested — it's easy to accidentally disable it in development and forget to re-enable it, or to have a bug that makes verification always pass.
Test your signature validation explicitly:
- Send a webhook request with an invalid signature — your endpoint should return 400 or 401, not 200
- Send a webhook request with a missing signature header — same, should reject
- Send a webhook request with a valid signature — should return 200
Add these as integration tests that run in CI. A monitoring check that verifies your endpoint returns 4xx for unsigned requests can also be set up as an HTTP monitor with an expected response code of 400.
Webhook monitoring checklist
| Check | How to monitor |
|---|---|
| Webhook endpoint is reachable | HTTP monitor (POST) on the endpoint URL |
| Consumer is processing events | Heartbeat monitor — ping after each successful process |
| Outgoing deliveries succeeding | Application metric: delivery success rate |
| Retry queue not backing up | Application metric: queue depth alert |
| Signature validation working | Integration test — invalid signature returns 4xx |
Monitor your webhook endpoints with PingBase
HTTP monitors for webhook endpoint reachability, heartbeat monitors for end-to-end processing verification. Free for up to 5 monitors.
Get started free →Related
Webhook Alerts: Connect PingBase to Anything
How to route PingBase alerts to any system using outgoing webhooks.
Heartbeat Monitoring for Cron Jobs
The same heartbeat pattern applied to scheduled tasks and background jobs.
How to Monitor Your API Endpoints
HTTP monitoring including POST endpoints, custom headers, and response body checks.