A redelivered webhook does not necessarily represent a new business action. Providers may retry delivery and sometimes offer manual redelivery. Establish which identifier denotes delivery and which identifies the underlying event in the actual provider contract.
GitHub documents identifiers including X-GitHub-Delivery. Do not assume another service uses identical semantics merely because a header has a similar name.
Decide before producing side effects
Verify authenticity and the intended event type according to provider guidance first. Then use persisted processing state to decide whether the business effect remains outstanding. A short-lived in-memory variable cannot provide protection after a restart.
A fictional state record might contain:
Event: demo-event-42
Delivery received: yes
Business record persisted: yes
Notification: pending
Received does not mean completely processed. Error handling should not recreate an already stored primary object merely because a notification is still pending.
Test repeated delivery, concurrent processing and restarts with isolated data, then inspect the actual number of resulting records. Compare stored records and pending side effects. Any additional external service also has its own retry semantics, so this design does not justify a blanket exactly-once guarantee.