Stripe Webhooks: Handle Payment Events Without Losing Data
Why Webhooks Are Hard Stripe calls your server when things happen: payment succeeded, subscription renewed, card declined. If your handler fails, Stripe retries. If your server is down, events queu...

Source: DEV Community
Why Webhooks Are Hard Stripe calls your server when things happen: payment succeeded, subscription renewed, card declined. If your handler fails, Stripe retries. If your server is down, events queue up. The failure modes are nasty: Process the same event twice → duplicate fulfillment Miss an event → user pays but doesn't get access Process out of order → subscription logic breaks Here's how to handle this correctly. Webhook Signature Verification Never process events without verifying they came from Stripe: import Stripe from 'stripe'; import { buffer } from 'micro'; // or read raw body const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); export async function POST(request: Request) { const body = await request.text(); const signature = request.headers.get('stripe-signature')!; let event: Stripe.Event; try { event = stripe.webhooks.constructEvent( body, signature, process.env.STRIPE_WEBHOOK_SECRET! ); } catch (err) { console.error('Webhook signature verification failed:', err); r