Самый простой и надёжный способ — стараться делать операции атомарными на уровне базы, чтобы не давать нескольким запросам одновременно «проскочить». Если это сложно — блокировки или идемпотентные ключи помогут. Главное — не оставлять дырку между проверкой и обновлением состояния, иначе race conditions будут гарантированы.