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:
-
Endpoint availability — is your
/webhook/stripeendpoint reachable and returning 2xx? - 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
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)
// 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);
});
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"
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
- Use Stripe CLI to send a test event:
stripe trigger payment_intent.succeeded - Verify the heartbeat ping fires in your Vigilmon dashboard
- Temporarily disable your route and verify Vigilmon alerts fire
- 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.
Top comments (0)