DEV Community

Vigilmon
Vigilmon

Posted on • Originally published at vigilmon.online

How to Monitor Your Stripe Webhooks with Vigilmon

Stripe webhooks are the heartbeat of your payment system. When a payment succeeds, a subscription renews, or a refund is issued, Stripe calls your webhook endpoint. If that endpoint goes down — even briefly — you miss critical payment events.

The risk isn't just losing data. Stripe retries failed webhooks with exponential backoff over 3 days. But if your endpoint is down during a high-volume period (Black Friday, a pricing migration, a billing cycle renewal surge), you can end up with thousands of queued events arriving all at once when your endpoint comes back up, overwhelming your database and queue workers.

This guide covers how to monitor your Stripe webhook endpoint with Vigilmon.

What to Monitor

Stripe webhook monitoring has two components:

  1. Endpoint availability — is your /webhook/stripe endpoint reachable and returning 2xx?
  2. Processing health — is your queue processing webhook jobs without backlog?

Step 1: Monitor Your Webhook Endpoint URL

Stripe calls your webhook endpoint via HTTPS. You can monitor the same endpoint from Vigilmon with a synthetic GET (or an authenticated check).

Simple availability check:

Monitor: GET https://yourapp.com/webhook/stripe
Type: HTTP(S)
Expected status: 405 (Method Not Allowed — GET on a POST endpoint is correct!)
Check interval: 1 minute
Enter fullscreen mode Exit fullscreen mode

Note: A 405 response on a GET request to a POST-only endpoint is a healthy response — it means the route exists and is routing correctly. A 404 means the route is broken. A 500 means something is wrong in your middleware.

Why 405 is the right expected status:

Most web frameworks (Laravel, Django, Rails, Express) return 405 when you call a POST-only route with GET. This tells you:

  • ✅ Your server is up
  • ✅ The route is registered
  • ✅ Middleware (CSRF, auth) didn't reject the request before it reached the handler
  • ✅ Your app is running correctly

Step 2: Monitor Webhook Processing with Heartbeats

Even if your endpoint is up, your webhook queue might be backed up. A Vigilmon heartbeat monitor catches this.

In your webhook handler, ping Vigilmon after successful processing:

# Python/Django example
@csrf_exempt
def stripe_webhook(request):
    payload = request.body
    sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
        )
    except ValueError:
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError:
        return HttpResponse(status=400)

    # Process the event
    handle_stripe_event(event)

    # Ping Vigilmon heartbeat to confirm processing is healthy
    import requests
    requests.get('https://hb.vigilmon.online/YOUR_HEARTBEAT_ID', timeout=2)

    return HttpResponse(status=200)
Enter fullscreen mode Exit fullscreen mode
// PHP/Laravel example
Route::post('/webhook/stripe', function (Request $request) {
    $event = Stripe::webhooks()->construct(
        $request->getContent(),
        $request->header('Stripe-Signature'),
        config('services.stripe.webhook_secret')
    );

    // Process event
    handleStripeEvent($event);

    // Heartbeat ping
    Http::get('https://hb.vigilmon.online/YOUR_HEARTBEAT_ID');

    return response('', 200);
});
Enter fullscreen mode Exit fullscreen mode

In Vigilmon, configure the heartbeat:

  • Grace period: 30 minutes (Stripe's least frequent event type triggers at minimum monthly intervals, but high-traffic apps process events every few minutes)
  • Alert: immediate on miss

Adjust grace period based on your Stripe event frequency. For a SaaS with daily active payments, 15-minute grace is appropriate.

Step 3: Monitor Your Stripe Dashboard Health Endpoint

Stripe provides a status API:

Monitor: GET https://status.stripe.com/api/v2/status.json
Type: HTTP(S)
Expected status: 200
Keyword check: "operational"
Enter fullscreen mode Exit fullscreen mode

This won't replace endpoint monitoring, but it helps you distinguish between "Stripe is down" and "our endpoint is down" during incidents.

Step 4: Set Up Escalating Alerts

Webhook downtime has a cost proportional to how long it's down:

Duration Impact
< 5 min Stripe retries cover it, minimal data loss
5-30 min Events queue up, some latency in processing
30-60 min Subscription renewals may be delayed, billing events stack
1-3 days Stripe abandons retries, you lose payment events permanently

Configure Vigilmon's escalating alerts:

  • 5 minutes down: Slack notification to engineering channel
  • 15 minutes down: PagerDuty page to on-call engineer
  • 30 minutes down: Email to CTO

Step 5: Test Your Monitoring Setup

  1. Use Stripe CLI to send a test event: stripe trigger payment_intent.succeeded
  2. Verify the heartbeat ping fires in your Vigilmon dashboard
  3. Temporarily disable your route and verify Vigilmon alerts fire
  4. Re-enable the route and verify the monitor recovers

Common Stripe Webhook Failure Modes

  • CSRF middleware: most frameworks have CSRF protection that rejects Stripe's POST requests. Always exclude your webhook route from CSRF middleware.
  • Body parsing: webhook signature verification requires the raw request body. Don't let your framework parse it to JSON before you verify.
  • Timeout: Stripe expects your webhook to return within 30 seconds. If your handler does heavy processing synchronously, queue the work and return 200 immediately.
  • Duplicate events: Stripe may deliver the same event multiple times. Your handler must be idempotent.

Start Monitoring Today

Vigilmon takes 5 minutes to set up. Add your Stripe webhook endpoint URL, create a heartbeat monitor, and connect your Slack or email for alerts.

Don't let a webhook outage cost you payment data.

Set up Stripe webhook monitoring for free

Top comments (0)