Skip to content

Conversation

@NikolasHaimerl
Copy link
Contributor

@NikolasHaimerl NikolasHaimerl commented Dec 10, 2025

Fix Race Conditions in Event Processing

The Problem
Our event ingestion pipeline was vulnerable to race conditions when concurrent processes indexed the same event. In PostgreSQL (Read Committed), checking for a row's existence does not lock the "gap" if the row is missing. This caused two processes to see null simultaneously, leading to "Duplicate Key" errors and aborted transactions.

The Solution
Implemented PostgreSQL Advisory Locks to strictly serialise processing for specific events without blocking the entire table.

Implementation Details

  1. Deterministic Locking: Generates a 64-bit hash from the event's unique keys (e.g., txHash + logIndex).
  2. Virtual Mutex: Acquires an exclusive lock on this hash (pg_advisory_xact_lock) before DB operations.
  3. Gap Safety: This acts as a "Virtual Gap Lock." If Process A and B receive the same event, Process B is forced to wait until A commits. Process B then sees the newly created row, preventing duplicate insertion attempts.

Benefits

  • Stability: Eliminates transaction failures caused by duplicate key constraints.
  • Performance: Locks are granular (per event ID), preserving high concurrency for unrelated events.
  • Integrity: Guarantees atomic "check-then-act" logic.

See: https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants