Skip to main content
Concurrency is a normal part of financial systems, where multiple transactions can try to read from or write to the same balance at the same time. Without the right controls, this can lead to race conditions, lock contention, and incorrect balance updates. This guide explains the main mechanisms Blnk uses to handle concurrent transaction processing safely. We’ll cover:
  1. Queueing transactions
  2. Distributed Redis balance locks
  3. Optimistic locking at the DB layer

Queueing transactions

Queueing means a transaction is first recorded as work to be processed, instead of being applied to the ledger immediately in the same request. Here is how it works: Blnk first saves the transaction in a QUEUED state. After that, a worker picks it up and applies it to the ledger. Transactions that affect the same balance are routed in a way that reduces them clashing with each other, while transactions for unrelated balances can still move in parallel.
By default, Blnk uses the queue when receiving a transaction request. Learn more: Transaction lifecycle

Skipping the queue

Blnk also supports skipping the queue and processing a transaction immediately in the same request by setting skip_queue=true. In this mode, Blnk no longer relies on the queue and uses the other safeguards to keep balance updates correct.

Distributed Redis balance locks

In Blnk, distributed locks are used to make sure two conflicting transactions don’t update the same balance at the same time. Here’s how it works:
  1. Blnk identifies the balance IDs involved in a transaction request. Next, it acquires Redis-backed locks for those balances before processing begins.
  2. Blnk locks balances in a consistent order to prevent deadlocks. Without this, one transaction could lock Balance A and wait for Balance B, while another locks Balance B and waits for Balance A creating a deadlock.
  3. If Blnk cannot acquire all the locks it needs, it releases any locks already acquired, then either waits and retries or fails, depending on your configuration.
  4. Once the locks are held, Blnk reads the latest balance state, validates the transaction, applies the update, and commits it atomically.
  5. After the commit, the locks are released.

Optimistic locking at the DB layer

Blnk also uses optimistic locking to make sure that a balance is only updated if it has not changed since it was last read. Instead of holding a database lock from the start, Blnk reads the balance, computes the new value in memory, and then tries to write that update back only if the balance is still in the same version it originally read. If another transaction updated the balance first, the write is rejected. Blnk does this using a version field on each balance. When a new transaction is recorded:
  1. Blnk reads the balances and their current version.
  2. Blnk computes the new balance value in memory, and then tries to update the balance only if the version is still the same.
  3. If the update succeeds, the version is incremented.
  4. If no row is updated, Blnk treats it as an optimistic locking conflict, which means the balance was changed by another transaction before this write could be applied.
In Blnk, optimistic locking acts as the database-level safety net.Distributed locks prevent conflicting transactions from running at the same time, while optimistic locking checks at write time that the balance has not changed since Blnk last read it.

Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool. To ask questions or discuss issues, please contact us or join our Discord community.
Tip: Connect to Blnk Cloud to see your Core data.You can view your transactions, manage identities, create custom reports, invite other team members to collaborate, and perform operations on your Core — all in one dashboard.Check out Blnk Cloud →