Atomic Updates (UpdateOp)
Perform atomic field-level updates on state and stream data without race conditions
The UpdateOp system lets you perform atomic field-level updates on both state and stream data. Instead of reading an entire object, modifying it, and writing it back (which creates race conditions when multiple Steps access the same data), you describe the operations and they are applied atomically.
The Problem
The traditional get-then-set pattern is not safe when multiple Steps run concurrently:
If two Steps read the same order simultaneously, one update will be lost.
The Solution
Use update() with UpdateOp[] for atomic operations:
All operations in the array are applied atomically — no data loss, no race conditions.
UpdateOp Types
| Type | Fields | Description |
|---|---|---|
set | path, value | Set a field to a specific value (overwrite) |
merge | path (optional), value | Merge an object into the existing value (object fields only) |
increment | path, by | Increment a numeric field by the given amount |
decrement | path, by | Decrement a numeric field by the given amount |
remove | path | Remove a field entirely |
Usage in State
Returns { new_value, old_value } — the same return type as state.set().
Python
Usage in Streams
The same UpdateOp types work on stream data:
Stream updates are also atomic and trigger stream events that connected clients receive in real-time.
Merge Operation
The merge operation performs a shallow merge of an object into the existing value:
If path is omitted, the merge is applied to the root object:
Common Patterns
Counter Tracking
Status Transitions
Parallel Step Completion
Combined with state triggers, this pattern enables powerful parallel-then-merge workflows without polling.