The first Stripe webhook bug that cost me actual money happened on a Tuesday. A user signed up for a paid plan, the checkout.session.completed event arrived, my handler created their workspace, and then Stripe retried the same event nine seconds later because my response had taken longer than the timeout. The retry created a second workspace. The user could see both. They picked the first one and ignored the second. A week later they cancelled because their data had silently been split across two accounts and they thought we were buggy. We were buggy. Not because the webhook code was wrong in any single line, but because I had treated webhooks like a normal API call. They are not a normal API call. They are a message queue with weird rules, and if you do not respect those rules you ship a product that quietly corrupts billing state. This post is the version of the webhook integration guide I wish I had read before shipping. The Stripe docs are good.…