Queryable state
What do you give up by reading a job's state directly?
Keyed state is already a partitioned key-value store. So exposing point lookups into it (get(restaurant 5)) seems to eliminate the sink write and the separate serving store. The mechanism is sound. The coupling is what kills it.
- Reads bypass the checkpoint boundary. You see uncommitted state. In database terms this is read-uncommitted: a read can observe a value that a later recovery undoes, because the job restores an older checkpoint.
- Serving traffic shares a process with processing. Heavy read load causes backpressure in the pipeline, and there is no isolation mechanism.
- The key-to-instance mapping is an internal detail that changes at every rescale. So clients need a discovery layer that tracks the job's internals.
- No availability during recovery, which is exactly when someone wants to know what happened.
Exporting to a serving store costs a write amplification (every update is written twice: to state and to the store) and a staleness window (the store is behind by up to a checkpoint interval). It buys isolation, a stable address, availability during job restarts, and committed reads. Most systems make that trade, and it is the right one except in cases that are low-cardinality, latency-critical, and tolerant of staleness.
| Queryable state | Export to serving store | |
|---|---|---|
| Extra write | none | one per update |
| Staleness | none (but uncommitted) | up to a checkpoint interval |
| Isolation from processing | none | full |
| Available during restart | no | yes |
| Stable client address | no (changes on rescale) | yes |
| Reads are committed | no | yes |