Skip to content

Transactions Design

Transactions provide atomic multi-operation updates. Single-group transactions commit through the owning Raft log. Cross-group transactions use a two-phase commit (2PC) coordinator so participating groups record the same decision. The current cross-group command builder supports map put and delete; putIfAbsent, set, queue, and other multi-structure operations remain single-group only. This page describes the transactional protocol path; non-transactional client LoomBatch requests use the separate batch-execution path.

The animation below follows one cross-group transaction through begin, prepare, decide, and commit — and the abort path when a prepare times out:

Cross-Group Transaction — Two-Phase Commitcommit path

Begin opens a server-side session and returns a transaction ID — the timeout starts here.

Client
begin()
put(a, 1)
put(b, 2)
commit()
Coordinator
session tx-42
staged ops
raft-0 decision
Group Aowns a
own Raft log
a = —
Group Bowns b
own Raft log
b = —
  • The transaction protocol path surfaces the ambiguous-outcome contract to clients when a replicated commit’s result cannot be confirmed.
  • Transaction session management owns coordinator-backed stateful sessions, drives the timeout monitor, and rebuilds recoverable state from committed entries and snapshots.
  • Single-map transactions evaluate condition, then, and else branches atomically against one named map (LoomMap). Multi-structure replicated commits are applied through the data-structure registry.
  • Multi-structure replicated commits acquire whole-structure locks (map/set/queue) in sorted (structureType, structureName) order to prevent deadlocks between concurrently committing transactions.
  • Optional transaction-scoped per-key locks (the wire Lock key step) are pessimistic and acquired one key per request. If another transaction already holds that key, the lock fails fast with a conflict error rather than waiting, so per-key locking never blocks or deadlocks.
  • Cross-group transactions use a prepare/decide flow.
  • Replicated transaction commits use a durable command format.

A transaction flows through the following message sequence:

  1. Begin — opens a server-side session and returns a transaction ID; the timeout starts here.
  2. Stage operation — stages an operation server-side against the named session.
  3. Lock key (optional) — acquires a transaction-scoped key lock for pessimistic reads.
  4. Commit — commits the session. When the message carries a non-empty payload, the server decodes the payload as a batched operation list and forwards it through the buffered-commit path; an empty payload commits the already-staged operations.
  5. Roll back — aborts the session and releases all locks.

These defaults are runtime safeguards. They are not exposed as documented Spring Boot properties, standalone properties, or YAML configuration keys. Application code can set the client-side transaction timeout per transaction with client.newTransaction(Duration).

ParameterDefaultPublic override
Transaction session timeout60 000 msclient.newTransaction(Duration) per transaction; otherwise the default applies
2PC prepare phase timeout30 000 msNone in public configuration
2PC decide phase timeout30 000 msNone in public configuration

The timeout monitor enforces the session timeout and releases all locks held by an expired session.

  1. The client builds a transaction whose keys resolve to one group.
  2. The commit request is submitted through that group’s Raft write path.
  3. The apply path validates locks and preconditions.
  4. The result is recorded with idempotency metadata.
  5. Retries after a dropped response return the recorded result.
  1. The coordinator splits the command into per-group slices.
  2. Each participant group prepares through its own Raft log.
  3. The coordinator records the final decision on raft-0.
  4. Participants receive COMMIT or ABORT decisions and acknowledge.
  5. Recovering participants query the coordinator for the recorded decision.

Once all prepare votes are collected, a single ABORT vote from any participant forces the decision to ABORT. The coordinator does not wait for remaining participants after a prepare timeout — non-responding participants are recorded as ABORT votes and the decision proceeds immediately.

  • A committed single-group transaction applies exactly once.
  • Participants never commit without a coordinator decision.
  • A lost client response does not cause duplicate apply on retry.
  • Transaction-scoped locks are released on commit, abort, rollback, timeout expiry, or recovery cleanup.
  • A stateful session that carries an owner binding (REST-originated and coordinator-owned sessions) is bound to the principal that opened it: the leader verifies the owner on the commit apply path, so a different principal cannot commit or roll back another principal’s transaction.

Leader failover during single-group commit may return an ambiguous outcome; clients should retry with the same transaction identity, and an owner-bound session must be resumed by the same principal. Coordinator failover recovers durable prepare/decide state from raft-0. Multi-coordinator-failover within a single in-flight 2PC transaction is not yet covered by automated crash tests. LoomCache does not claim XA semantics.

Transaction commit/rollback, failover, coordinator durability, cross-group 2PC, idempotent retry, and lock-path tests cover this layer. Operators watch cross-group prepare/decide duration, aborts, recoveries, commit latency, and boundary exceptions.

  • Raft Design — Raft log and leader election that back the single-group and coordinator commit paths.
  • Persistence Design — WAL and snapshot mechanics that make committed transaction state durable across restarts.

LoomCache is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Hazelcast, Inc. or by any other company whose products are named in this documentation. “Hazelcast” is a trademark of Hazelcast, Inc.; references to it are nominative and describe only migration and comparison. All other product and company names are trademarks of their respective owners and are used for identification purposes only.