Skip to content

Build1 publisher3 min readPublished Updated

An AI-written Stripe handler acknowledged the webhook before it saved the payment row

A developer who let AI write every line of application logic for 30 days now merges nothing until a second model in a clean context has tried to break the diff and failed. The post credits two different fixes.

The Engineer · Build desk

What happened

  • An AI-written Stripe webhook handler verified the event, returned a 200 to Stripe, and only then awaited the database write that recorded the payment.
  • The author says that diff passed every test, read beautifully, and would have lost a paying customer their money the first bad night in production.
  • The experiment behind it ran 30 days, with the author refusing to type a line of application logic and letting AI write all of the code.
  • The rule the author settled on is that nothing merges until a second reader whose only job is to break the code has tried and failed.
  • The reviewer prompt tells the model the code is broken, supplies four failure assumptions to try, and demands the exact scenario that loses data or loses a customer money.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint For ordering bugs of this shape a green suite cannot serve as the merge gate, because the assertion the test makes is independent of the write it is meant to protect.
  • decision A team can take the cheap half of the rule by editing one prompt, while the different-family half needs a second vendor account and whatever approval that carries.
  • contradiction Two of the author's own explanations compete, so a reader cannot tell from this account whether to spend on a second model or on a second prompt.

The ordering is the part a test suite cannot see. Once `res.sendStatus(200)` has run the response is committed, so an exception from the awaited `db.savePayment(event)` cannot change the status Stripe already has [15]. A test that asserts the endpoint answers 200 passes whether or not the row was ever written [16].

The author's objection to self-review is about the objective, not the model's ability. "Confidence is the output. Correctness is a coincidence you're hoping rides along," the author wrote [4]. Asking a model whether its own code is correct is asking it to agree with itself, and the dev.to post calls that "worse than useless" [5]: "It grades its own homework in a slightly more formal voice and hands you back an A" [6].

The rule has three parts, and the author says skipping any one collapses it back into an echo [7]. The reviewer needs a clean context, because the writing context has already spent 4,000 tokens convincing itself the code is right [8]. The reviewer should come from a different model family, on the argument that two models from one family share the same blind spots [9]. And the reviewer's default is inverted: it is told the code is broken, and if it cannot find the failure it has to say so explicitly and explain what would have to be true for that to be the case [11].

One of the four assumptions the prompt hands the reviewer is "the database write fails AFTER the external call succeeds" [11]. That is the shape of the webhook handler [17]. A checklist assembled from failures you have already had will find failures of the kind you have already had. I would still run it; it is not a general search.

The post's two explanations compete. "The single highest-leverage change I made all month was pointing the reviewer at a different model than the author," the author wrote [10]. On the adversarial prompt, the same post says: "Same model. Same weights. Completely different output, because the objective is the reviewer, not the model" [12]. The account does not separate the two effects [20].

The worked example predates the rule. The author introduces the handler as "the exact diff that started all of this" [23], and the practice came out of it [21]. The job left to the person, in the author's words, is "to hold the one thing neither agent has: the memory of having been burned" [22].

Adoption costs two inference passes per merged diff, with the diff re-sent in full because the reviewer's context has to be clean of the writing session [18]. The author says you can adopt the rule "today without changing a single tool" [13]. That is true of the prompt. A second model family is a second account. In my view the order is to run the break-it prompt against the model you already pay for, count what it returns over a month of diffs, and buy the second vendor on that number.

What to watch

  • A published count of diffs the break-it reviewer rejected, measured against the same model asked to review normally, would show which of the three parts is earning the second pass.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories