Mutation
Mutations in Actionbase allow you to insert, update, and delete edges in your graph. The mutation process ensures data consistency, durability, and write-time optimization.
For the conceptual foundation, see Core Concepts.
Mutation Flow
Section titled “Mutation Flow”The complete mutation process:
flowchart TD
Request([Mutation Request
with Event, Operation]) --> WAL[Write WAL]
WAL --> Lock[Acquire Lock]
Lock --> Read[Read State
from datastore]
Read --> Modify{State exists?}
Modify -->|Yes| ApplyEvent[Apply Event]
Modify -->|No| InitialState[Initial State]
InitialState --> ApplyEvent
ApplyEvent --> ComputeAdditionalInfo[Compute Index, Count
based on changed States]
ComputeAdditionalInfo --> Write[Write State with AdditionalInfo
to datastore]
Write --> Release[Release Lock]
Release --> CDC[Write CDC]
CDC --> Response([Response])
Mutation Request
Section titled “Mutation Request”A mutation request contains:
- Event: The data change to be applied (e.g., new property values, edge creation)
- Operation: The type of operation:
- Insert: Create a new edge
- Update: Modify an existing edge
- Delete: Remove an edge
Mutation Process
Section titled “Mutation Process”1. Write WAL (Write-Ahead Log)
Section titled “1. Write WAL (Write-Ahead Log)”Before any changes are made to the datastore, the mutation is written to the Write-Ahead Log (WAL). This ensures durability and enables recovery in case of failures.
In production, Actionbase uses Kafka as the WAL backend. The WAL can be replayed to restore the final state, even if events arrive out of order.
2. Acquire Lock
Section titled “2. Acquire Lock”To prevent concurrent modifications, Actionbase acquires a lock on the specific edge being mutated:
- Unique edges: Locks based on (source, target) pair
- Multi edges: Locks based on edge ID
3. Read State
Section titled “3. Read State”The current state of the edge is read from the datastore, including all existing properties, timestamps, and metadata.
4. Apply Event
Section titled “4. Apply Event”The event is applied to the state, transitioning it based on the operation type:
- INSERT: Updates
createdAttimestamp and sets properties. The state becomes active whencreatedAt > deletedAt. - UPDATE: Updates only the specified properties without changing timestamps.
- DELETE: Updates
deletedAttimestamp and marks properties as deleted. The state becomes inactive whendeletedAt >= createdAt.
The transition respects version ordering—newer versions override older ones.
5. Compute Indexes and Counters
Section titled “5. Compute Indexes and Counters”Based on the changed state, Actionbase computes additional structures for fast reads:
- Indexes: Old indexes are deleted, new indexes are created based on the changed state
- Counters: Counts are incremented or decremented
This write-time optimization ensures read queries can be answered quickly without expensive computations.
6. Write to Storage
Section titled “6. Write to Storage”The modified state along with indexes and counters is written atomically to the datastore.
7. Release Lock
Section titled “7. Release Lock”Once the write is complete, the lock is released.
8. Write CDC (Change Data Capture)
Section titled “8. Write CDC (Change Data Capture)”The mutation is recorded in the CDC system for downstream systems. In production, Actionbase uses Kafka as the CDC backend.
CDC stores the resulting state after processing, enabling synchronization to external systems (e.g., Iceberg, MPP, Trino) for analytics.
Event Ordering
Section titled “Event Ordering”Clients attach timestamps to events (typically millisecond or nanosecond precision). Even if network delays cause events to arrive out of order, Actionbase uses the original timestamps to compute the correct final state.
Example: If ON/OFF events arrive as ON, OFF, ON, OFF but were originally ON, ON, OFF, OFF, Actionbase ensures the final state is correct based on timestamps.
This mechanism ensures eventual consistency—the final state is always correct regardless of event arrival order.
Write-Time Optimization
Section titled “Write-Time Optimization”During mutations, Actionbase pre-computes:
| Structure | Purpose | Query Type |
|---|---|---|
| EdgeState | Current edge state | Get |
| EdgeIndex | Sorted index entries | Scan |
| EdgeCounter | Aggregated counts | Count |
Benefits:
- Fast Reads: No query-time computation needed
- Consistent Performance: Read latency remains low regardless of data size
- Efficient Storage: Indexes and counters are maintained incrementally
By computing at write time, Actionbase shifts computational cost from reads to writes—ideal for read-heavy workloads.
Consistency Guarantees
Section titled “Consistency Guarantees”The mutation process ensures consistency through:
| Mechanism | Guarantee |
|---|---|
| Locking | Prevents concurrent modifications |
| Atomic Writes | State and indexes written together |
| WAL | Durability and recovery |
| Read-Modify-Write | Mutations based on latest state |
| Timestamp Ordering | Correct final state despite out-of-order events |
Next Steps
Section titled “Next Steps”- Query: How to read the pre-computed data
- Datastore: Datastore backend details
- API Reference: Complete mutation API