Stripe Webhooks & Token Buckets
Structuring subscription-based SaaS requires a reliable Stripe webhook handler. We use Express middleware to verify signing signatures and update user quotas in our database dynamically based on payment successes or failures.
The Webhook Idempotency Problem
Stripe may send the same webhook event multiple times. If your system isn't idempotent, a user might receive 3 months of credit for a single payment. We store processed `stripe_event_id`s in a Redis cache or database table to silently ignore duplicate events.
const eventId = stripeEvent.id;
const isProcessed = await db.processedEvents.findById(eventId);
if (isProcessed) return res.status(200).send('Already processed');
await processSubscription(stripeEvent);
await db.processedEvents.insert({ id: eventId });Handling Failed Payments (Dunning)
When a credit card fails, we don't immediately lock the user out. The architecture must support a 'past_due' status, initiating a Dunning email sequence (Days 1, 3, 7) before automatically downgrading the account to the free tier.