Processing an event only once is an extremely hard problem to solve in a distributed context like you describe.
Instead of reinventing a (very) complex wheel, you should consider:
- either to rely on middleware that can handle this challenge for the event queue,
- or think of a more robust design, in relation to multiple processings of the same event.
For the first option, Kafka for example has this feature since 2017. Here a blog post from Neha Narkhede (Confluent's co-founder and Chief Technical Officer) who explains how this works. Note the the "exact once" delivery just ensures that that the event is delivered exatly once: you'd still have to add some logic to ensure that the processing takes place.
For the second option, you could check if you really need "exact once". If it is confirmed, you could try to design your processing in an idempotent manner. If this is not possible, it becomes more complex: you'll need to combine transactional processing (e.g. a shared database, but this might become a bottleneck if you have very high volumes) with some trick to avoid repetition (e.g. keeping a hash of the messages already processed, keep the id or the timestamp of the last message processed if your middlewaren ensures delivery in-order).