stripe will send you the same webhook more than once, and it's right to. the question is whether your handler notices.
webhooks are how an external service tells your backend something happened. a payment went through, a subscription renewed. the awkward part is the delivery guarantee. to make sure you never miss an event, stripe promises to deliver each one at least once, which is a polite way of saying sometimes more than once. retries after a timeout, redeliveries after a blip, the same event arriving twice a few seconds apart. if your handler treats every delivery as fresh, you process the same payment twice, and now your data is wrong in a way that's hard to walk back.
the fix is to make the handler idempotent, which just means handling the same event twice has the same effect as handling it once. each event carries an id. i record the ids i've already processed, and if one comes back, the second pass recognises it and does nothing. the work happens exactly once no matter how many times the message arrives. a retry becomes a no-op, which is exactly what you want it to be.
writing that is easy. trusting it is the part that takes work, because the failure mode only shows up under concurrency, when two copies of the same event land at the same instant and both check "have i seen this?" before either has finished writing. so i didn't just assert it was safe. i load-tested it, firing events at the endpoint under realistic concurrency and deliberately replaying duplicates and retries to watch what happened. the test is the difference between believing the handler is idempotent and knowing it.
the broader habit is the thing i'd keep. anywhere a system can be told the same thing twice, and a surprising number of places can, assume it will be and make the second time harmless. then prove the second time is harmless before you call it done, because "should be fine" is not a property you can rely on at three in the morning.