ElectricSQL provides transactional causal+ consistency with rich-CRDTs.
Transactional causal+ consistency (TCC+) combies causal consistency, CRDTs, highly available transactions and sticky availability. It is formally proven to be the strongest possible consistency mode for an local-first database system.
ElectricSQL also extends TCC+ with Rich-CRDT techniques to preserve relational invariants.
Causal consistency guarantees that if a read or write depends on the effects of a previous write then the causal order between them will be respected. However, if two operations are concurrent and have not seen each other, then it's fine for them to be applied in any order. It also implies that you read your own writes. As per the Jepsen Consistency diagramme below:
Martin Kleppmann has some great videos (on causal consistency and on logical time) and you can read the original "don't settle for eventual" paper here.
CRDTs are data types that can merge concurrent writes without conflicts. They allow clusters to accept writes without cross-region synchronization / replication consensus. Instead, writes can be accepted with low latency and replicated asynchronously, with commutative merge operations ensuring that all clusters converge on strong eventual consistency.
Highly available transactions
Highly available transactions guarantee the atomic application of a set of operations. I.e: you can wrap multiple writes within a transaction and those writes will either all be applied or none will be applied. See the paper for more information about the guarantees available under high availability and sticky availability.
High availability allows writes to be accepted at every server, wherever it is in the world. Sticky availability is a mode of high availability where clients always talk to the same server. When this condition is true, it allows high-availability systems to provide additional consistency guarantees, including read-your-own-writes and causal consistency.
Rich-CRDT extend TCC+ with additional techniques to preserve relational invariants. This is key to supporting relational data models from existing Postgres-backed applications.
The primary techniques are:
- composition — composing CRDTs into higher-order data types
- compensations — applying additional operations during concurrent merge logic
- reservations — runtime coordination via shared, distributed locks
Currently, we apply compensations to preserve referential integrity. In future, we will implement more techniques to support additional relational constraints.