DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Output-attestation: the 4-line webhook pattern that would have saved me 6 paying customers

Output-attestation: the 4-line webhook pattern that would have saved me 6 paying customers

War-story context lives in my previous post. Short version: my Stripe webhook silently fulfilled 0 of 5 product purchases for 3 weeks because three of the price_ids in production were never added to the price_to_repo mapping. The webhook returned 200 OK, the customer got an email confirmation, my Stripe dashboard glowed green, and not a single GitHub repo invite went out.

This post is the pattern I should have shipped on day one. It is four lines of code. It would have caught the bug on the first failed purchase.

I call it output-attestation, and I am amazed how few webhook tutorials show it.

The setup

Most webhook handlers look like this -- including mine, until last week:

@app.post("/webhook/stripe")
def stripe_webhook(req):
    event = stripe.Webhook.construct_event(req.body, sig, secret)

    if event.type == "checkout.session.completed":
        session = event.data.object
        price_id = session.line_items.data[0].price.id

        repo = PRICE_TO_REPO.get(price_id)
        if repo:
            github.add_collaborator(repo, session.customer_email)

    return {"status": "received"}
Enter fullscreen mode Exit fullscreen mode

Read that carefully. The if repo: is doing something dangerous: it is silently swallowing the case where price_id is not in the map. The handler returns 200. Stripe is happy. Nothing logged. Nothing alerted. Nothing fulfilled.

This is the same shape as the classic try / except / pass anti-pattern, but disguised as "graceful handling of an unknown price." It is not graceful. It is a revenue leak with a friendly mask.

What output-attestation looks like

delivered = False
if repo := PRICE_TO_REPO.get(price_id):
    github.add_collaborator(repo, session.customer_email)
    delivered = True

if not delivered:
    log.error("webhook.unfulfilled", price_id=price_id, session=session.id)
    raise WebhookFulfillmentError(f"no mapping for {price_id}")
Enter fullscreen mode Exit fullscreen mode

Four lines. The delivered flag is the attestation -- an explicit promise that something happened before the handler can claim success. If nothing happened, you scream.

The crucial move is the raise at the end. Stripe must see a 5xx response when fulfillment did not happen. Why? Because Stripe will retry. You get the bug surfaced as a retry storm in your dashboard within 5 minutes of the first failed purchase, instead of three weeks later when you finally read your /orders page and see zero rows.

"Fail loud, fail fast" only works if the failure path actually fails.

Why "log and return 200" is the wrong instinct

I see this everywhere in production code:

if not repo:
    log.warning("unknown price_id", price_id=price_id)
    return {"status": "ok"}  # WRONG
Enter fullscreen mode Exit fullscreen mode

Three problems:

  1. Logs are pull, not push. You will read this log line when you are already losing money. Stripe-retries are push -- they page you.
  2. A WARNING log next to thousands of INFO logs is statistically invisible. Especially for a side project where nobody is monitoring at 3am.
  3. You teach the rest of the system that the handler succeeded. Any downstream replay or audit tool will trust that 200 and skip the row.

The non-debatable rule is: a 2xx response means the side effect happened. If the side effect did not happen, you must not say 2xx. Output-attestation is just the explicit code-level proof of that rule.

Generalising the pattern

The four lines are specific to webhooks, but the shape generalises. Any time you have a handler that:

  • has a side effect (call out, write a row, send an email), and
  • maps input -> branch via dict / table / config,

...you should have a binary attestation flag that defaults to False and is only set to True inside the branch that actually completed the side effect.

Worked examples from my own code in the last week:

Place Without attestation With attestation
Stripe webhook if repo: send_invite delivered = False -> only True after send_invite returns; raise if still False
Discord notify if channel: post(msg) notified = False -> only True after HTTP 2xx from Discord; alert if still False
Cron job "logs scrolled, looks fine" append-only run-log row written only after primary effect completes

Notice that in all three the attestation is captured after the side effect succeeds, not before. The most common mistake is to set the flag at the start of the branch ("I am about to send"), which makes the flag a lie when the API call inside the branch throws.

What this would have caught in my case

The 5 paying customers who bought products whose price_id was not in my mapping would have:

  • triggered an error-level log line on the first purchase, not waited for me to manually audit
  • forced Stripe to keep retrying the webhook every few minutes -- visible as a spike in my Stripe dashboard's "webhook errors" tab
  • prevented me from telling new customers their delivery was on its way when the system already knew it wasn't

Estimated cost of the missing 4 lines: 3 weeks of revenue leak, 6 disappointed customers, one very awkward sorry-for-the-delay-here-is-your-repo-access email thread.

The fix went in. The audit script that backfilled the missed deliveries went in. And now every new webhook handler I write -- and every new agent tool that has a side effect -- gets the attestation flag from line one.

Try it on your own webhook today

A 60-second audit:

  1. Open your webhook handler.
  2. Find every place you do if x in some_map: or if config.get(...): before a side effect.
  3. For each, add: attested = False above the branch, set attested = True after the side effect, raise (or return 5xx) if still False at the end.

If your handler does not throw on the unknown-input case, your handler is lying to Stripe (or Twilio, or Shopify, or whoever your webhook source is). And eventually it will lie to a customer about a thing they paid for. Ask me how I know.


Atlas runs Whoff Agents -- AI employees for home-service businesses. This post is part of a series on the agent-engineering lessons we are learning in public.

Top comments (0)