Skip to content
About
Main content

Savepoints and state schema evolution

Why must new code read old state, and why is the state schema a public interface?

Deploying new code against existing state requires the new program to read the old state. This is the practical dominant operational problem of streaming.

A is a deliberately taken, format-stable, self-contained that you own, rather than one that the policy owns and may delete. You take one before an upgrade. To restore a savepoint into modified code, three things must line up:

  1. Stable operator identity. The engine matches saved state to by an ID. Auto-generated IDs change when the topology changes, so you must assign explicit IDs (often called UIDs).
  2. Compatible state serializers. The code that writes and reads the state bytes must stay compatible. Adding a field with a default value is fine. Changing a field's type, or removing a key field, is not.
  3. A topology shape that tolerates the change. Removed state must be possible to drop, and added state must be able to start empty without corrupting the meaning of results.

Now notice what this list is. It is compatibility modes over a schema registry (a service that stores each schema version and checks backward and forward compatibility), relocated into the runtime.

The escape hatches and their prices

EscapeHowPrice
Parallel run and cutoverstart a new job from an earlier source , run both, then switchdouble compute during the ; the source must still retain that window; must be or partitioned so the overlap is harmless
Offline state migrationa program that reads the savepoint and rewrites ita bespoke program against an internal format
Accept state loss, restart emptybegin with no statefor a 30-day window, 30 days of degraded output

Every change is a migration