Transaction Isolation and Consistency

Twisp provides snapshot isolation and strong consistency to ensure correctness and prevent anomalies in ledger systems.

Transaction Isolation in Twisp

In systems that demand correctness and high concurrency, transaction isolation plays a critical role in ensuring consistency and preventing anomalies. Twisp leverages an ACID Multi-Version Concurrency Control (MVCC) transaction layer to implement robust isolation levels tailored to the needs of ledger systems.

Twisp's MVCC provides:

  • Interactive transactions: Supports all-or-nothing semantics for transactions, ensuring atomicity and isolation.
  • Snapshot Isolation: Transactions operate on a consistent and isolated view of data, ensuring transactions operate on immutable data snapshots.
  • Anomaly prevention: Guarantees that transactional operations produce fully consistent results without partial or invalid reads along with write skew prevention.
  • Strong consistency: Committed records and balances are readable in a strongly consistent manner through reads by ID, lookups by unique key, and most indexes, with no anomalies or partial updates. A few listing indexes are eventually consistent; see Eventually Consistent Listings.

Twisp runs and maintains a formal model of our MVCC transaction layer. Learn more about the formal modelling process we conducted with our partner Galois.

Isolation Levels Overview

Twisp supports four distinct transaction isolation levels, balancing between performance and correctness:

  1. Read Committed:

    • Ensures that the most recently committed data is visible to a transaction.
    • Use cases: Workflows requiring real-time, consistent reads that can tolerate a non-snapshot view of data.
  2. Snapshot Isolation (System Default):

    • Guarantees that transactions operate on a point-in-time consistent snapshot of the data.
    • Use cases: Workflows requiring strong correctness without paying a performance penalty.
  3. Repeatable Read:

    • Guarantees that read data has not changed on transaction commit providing read stability.
    • Use cases: High-consistency workflows for complex, interactive, multi-row updates.
  4. Serializable:

    • In addition to read stability, also provides phantom avoidance that ensures scans would not return additional data on transaction commit.
    • Use cases: Workflows where absolute correctness outweighs performance concerns.

Transaction isolation settings can be set with the @tx directive in GraphQL.

Preventing Transaction Anomalies

In high-concurrency environments, transaction anomalies can corrupt data or lead to business-critical errors. Twisp's isolation levels guard against common database anomalies. The following anomalies are thoroughly tested in every build via our conformance test suites:

  • G0: Write Cycles (dirty writes)
  • G1a: Aborted Reads (dirty reads, cascaded aborts)
  • G1b: Intermediate Reads (dirty reads)
  • G1c: Circular Information Flow (dirty reads)
  • OTV: Observed Transaction Vanishes
  • PMP: Predicate-Many-Preceders
  • P4: Lost Update
  • G-single: Single Anti-dependency Cycles (read skew)
  • G2-item: Item Anti-dependency Cycles (write skew on disjoint read)
  • G2: Anti-Dependency Cycles (write skew on predicate read)

By addressing these anomalies, Twisp's isolation levels ensure correctness and make ledger operations easy to reason about, even under high concurrency.

Strong Consistency

Twisp ensures strong consistency for reads by ID, lookups by unique key, and every index that is written in the same transaction as its record, guaranteeing that every transaction reflects an accurate state of the ledger. These reads see your own writes, including earlier writes in the same transaction, with no stale or partial results.

Eventually Consistent Listings

Some listings read from asynchronous indexes, which Twisp updates after the write commits. Examples are accounts by NAME, STATUS, or CODE without an eq filter, AccountSet.members, and the actions and executions lists. The Built-In Async Indexes table lists them all. Through these listings:

  • A record that was just created or changed can be missing for a short time after the write commits, usually under a second.
  • Within one transaction, records the same transaction wrote are not included. This holds for every operation in one GraphQL request, a tool call, and an MCP program program.

To read a record you just wrote, read it by ID, such as account(id:), or by a unique key, such as accounts(index: {name: CODE}, where: {code: {eq: "..."}}).

Custom indexes created with async: true are eventually consistent. Customer defined search index documents are replicated in an eventually consistent manner to OpenSearch.

Customer defined vector indexes are eventually consistent in two stages: a background worker embeds each committed change, and the vector index then applies it. Read-your-writes is not guaranteed, so a record written in one transaction may not appear in a vector query that runs just after it. Vector query results are always read at the query's snapshot, so a result never shows a record that was deleted, or that no longer matches the query's partition, filters or constraints. See Vector Indexes.

Balance Calculations

For high-volume, concurrent entry posting to concurrent-enabled accounts or aggregates, Twisp implements a non-blocking, transactionally consistent, and deterministic balance update process. The following balance types are provided to allow context-specific balance retrieval consistency without compromising correctness.

StateDescriptionUse Case
ProvisionalIncludes in-flight, uncommitted transactions along with committed changes.Enforce velocity controls on to-be-committed transactions.
PreparedCombines finalized balances with committed, but not-yet-finalized entries. Guaranteed to provide the exact same results as the final balance.Systems requiring transactionally consistent balances on concurrent-enabled accounts.
FinalReflects the fully committed and finalized state of the account. Finalized balances are cached.Systems that require the highest performance balance reads and can tolerate slightly stale balance values.

For concurrent-disabled accounts, the Prepared balance state is skipped and the balance update process proceeds directly to Final from Provisional.

Previous
Financial Ledger Database