Messaging platforms retry webhooks. Sellavie expected that: incoming events were recorded with a deduplication key, and an event already seen was skipped. On paper the duplicate path was correct.
In practice, retried events were being processed again as if they were new.
Where the failure actually was
The application supports two databases through a compatibility adapter. To make inserts behave the same on both, the adapter appended a clause asking for the new row's id.
Almost every table has an integer id, so this was harmless. The table that records incoming webhooks does not. Its identity is the deduplication key itself.
So the insert asked for a column that does not exist, and failed. That alone would have been noticed. What hid it was that recording the event was wrapped in a best-effort error handler, on the reasoning that a logging problem should not stop a message being handled. The failure was swallowed, nothing was recorded, and the next retry found no record of the first delivery.
Deduplication had been switched off without a single error reaching anyone.
Why it mattered
For a product that replies to customers, processing the same message twice can mean a duplicate reply, duplicate model work, or a repeated action on an order.
The repair
I did not add another check in the request handler. The handler was already correct. I taught the adapter that this table has no id, and added regression tests that deliver the same event twice and assert it is handled once.
What I took from it
Idempotency is only as strong as the lowest layer that can misreport whether something was saved. And an error handler that swallows failures to keep things moving should never be wrapped around the write that makes the operation safe to repeat.