Strict serializability on FoundationDB¶
fdyno runs each normal data operation in a FoundationDB transaction. FoundationDB documents these transactions as strictly serializable.
Definition¶
Serializability means that committed transactions have the same result as one serial order. Linearizability adds real-time order: if operation A completes before operation B starts, A must appear before B.
Strict serializability requires both properties.
fdyno transaction path¶
A normal fdyno write uses one transaction callback:
val, err := s.db.Transact(func(tr fdb.Transaction) (any, error) {
// Read the item and evaluate conditions.
// Write the base item, indexes, stream record, and token.
return result, nil
})
FoundationDB processes the callback as follows:
- It assigns one read version. Reads use one MVCC snapshot at that version.
- It buffers writes until commit.
- It checks whether later commits conflict with the transaction's read ranges.
- It rejects a conflicting attempt. The callback can run again at a newer version.
- It assigns an accepted transaction a commit version and makes the commit durable before returning success.
The callback must keep attempt-local state because FoundationDB can run it more than once.
Concurrent updates¶
Lost update¶
Two clients can read the same counter and calculate the same next value. FoundationDB detects that the second commit read a key changed by the first commit. The second attempt runs again with the new value.
DynamoDB ADD updates also perform the increment atomically inside the transaction.
Write skew¶
Two transactions can read one invariant and write different keys. FoundationDB adds conflict ranges for normal key and range reads. If one transaction invalidates the other transaction's read, both cannot commit from the same old state.
A range read also protects against a concurrent insert in that range. The insert conflicts with the recorded read range.
These results depend on the keys and ranges that fdyno reads. An application invariant that is not read and checked in the transaction is not protected automatically.
Scope¶
Strict serializability applies to one FoundationDB transaction.
It does not make separate HTTP requests atomic. Use TransactWriteItems when several
writes must commit together.
Each Query or Scan page is a separate read transaction. A later page can observe
writes that committed after the earlier page. LastEvaluatedKey stores a key position,
not a FoundationDB read version.
Operational limits¶
Strict serializability has these effects:
- During a partition, a component that cannot reach the required FoundationDB quorum cannot accept commits.
- Conflicting transactions retry and can reach the request deadline.
- Each transaction must fit FoundationDB's size, key, and time limits.
fdyno returns errors instead of serving a process-local stale copy when FoundationDB cannot provide the required transaction.
See Consistency for operation scope and Transactions for retry and failure behavior.