DEV Community

SaaSFactory
SaaSFactory

Posted on

3 Python Webhook Bugs That Only Show Up in Production (Flask + Stripe)

You wrote a webhook handler in Flask. It works perfectly on your laptop with the Stripe CLI. Then you deploy, and it silently breaks. Here are the 3 bugs that cause this, in order of how often I see them.

1. You parsed the body before verifying the signature

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_json()  # WRONG: this re-serializes the body
    sig = request.headers.get('Stripe-Signature')
    event = stripe.Webhook.construct_event(payload, sig, secret)
Enter fullscreen mode Exit fullscreen mode

request.get_json() parses and re-encodes the JSON. Even one whitespace difference between what Stripe sent and what Python re-serializes will make the signature check fail. You must pass the raw bytes:

payload = request.get_data()  # raw bytes, untouched
event = stripe.Webhook.construct_event(payload, sig, secret)
Enter fullscreen mode Exit fullscreen mode

This passes every local test (Stripe CLI forwards raw bytes correctly) and fails randomly in production behind certain proxies/CDNs that re-encode the body.

2. You used the wrong secret for the environment

Each endpoint (CLI forwarding, live webhook, sandbox webhook) has its own signing secret starting with whsec_. Hardcoding the CLI's secret works great until you deploy, where the real endpoint's secret is different. Pull it from an env var per environment, never a shared constant.

3. You didn't handle clock skew

construct_event checks the Stripe-Signature timestamp against your server clock and rejects anything outside a default 5-minute tolerance. Local dev machines with unsynced clocks, or containers that boot with the wrong time, pass locally (small drift) and fail in prod (bigger drift or NTP misconfig). If you see intermittent Timestamp outside the tolerance zone errors, check date on the server before touching the code.


I turned the checks I run on every Stripe integration I audit into a 7-rule CSV checklist (raw body handling, secret rotation, tolerance window, idempotency, retry handling, and 2 more). It's $5, instant download: https://buy.stripe.com/eVq6oGbBj7m23XZcNO7IY0k -- full refund if it doesn't save you time.

Top comments (0)