Use an event key and a recorded state
A trigger source may deliver the same event again after a timeout or acknowledgement problem. Store an idempotency key or processed-event record in a durable place that later runs can check.
Mark an event as complete only after the intended work is committed. If processing has multiple stages, record stage status so a retry can resume safely instead of treating a partially completed event as new.
Handle simultaneous deliveries
Two runs may check for the same event at nearly the same time. Use a unique constraint, atomic claim, or other coordination supported by the data store so both do not pass the duplicate check before either records completion.
Test repeated and concurrent delivery with a safe sample and inspect the final state. Keep the event key long enough to cover the source's retry window, and avoid retaining full payloads longer than needed.