Production SaaS
Stripe webhooks without double-charging customers
Billing is the one part of a SaaS where a small bug becomes a phone call. The usual culprit is the webhook. Payment providers deliver events reliably, which means they also deliver them more than once. If your handler naively creates a subscription, grants access, or sends a receipt on every delivery, you will eventually double-provision an account or charge a customer twice.
Rule one: verify the signature
Anyone can POST to a public URL. Before you trust an event, verify its signature against your endpoint secret. If the signature does not match, reject the request and move on. This one step filters out forged events and is the difference between a webhook you control and one an attacker does.
Rule two: make it idempotent
Idempotency means the same event, delivered twice, has the same effect as once. The clean way to do it is to key on the provider's event ID. When an event arrives, check whether you have already processed that ID; if you have, acknowledge and skip. Store processed IDs somewhere durable, and make the check part of the same transaction that changes state.
Rule three: acknowledge fast, work safely
Respond quickly so the provider does not retry while you are still working. If the work is heavy, acknowledge and process it asynchronously. Handle failures with retries and a dead-letter path so a single bad event does not stall everything else.
Rule four: model the lifecycle
Subscriptions are a state machine, not a single event. Trials start and end. Payments fail, then succeed on retry. Customers upgrade, downgrade, pause, and cancel. Map those states and decide, for each, exactly what your app should do. Billing bugs are almost always unhandled states, not broken code.
This is why ShipStack treats billing as an architecture problem rather than a single integration. You build the subscription model, verify signatures, dedupe by event ID, and handle the whole lifecycle in test mode before a real dollar moves. Boring to build, and exactly the kind of boring that keeps you out of trouble at 2 a.m.
Ship billing that behaves. Explore ShipStack