Savepoint
A savepoint is a snapshot of a streaming job’s state that an operator triggers deliberately and then owns, used to stop the job and start it again โ with different parallelism, different code, or a different version of the engine. Apache Flink describes it as “a consistent image of the execution state of a streaming job, created via Flink’s checkpointing mechanism,” consisting of “a directory with (typically large) binary files on stable storage (e.g. HDFS, S3, โฆ) and a (relatively small) meta data file.”
The difference from a checkpoint is ownership
A checkpoint is taken by the engine on a schedule so that a failed job can resume by itself; it belongs to the system, and the system decides when to discard it. A savepoint is taken because a person asked for one, and the files stay under that person’s control โ in Flink’s NO_CLAIM mode, “Flink will not assume ownership of the snapshot. It will leave the files in user’s control and never delete any of the files.”
That ownership is what makes the other properties useful. A savepoint “can generally be moved by moving (or copying) the entire savepoint directory to a different location, and Flink will be able to restore from the moved savepoint,” so it can be kept as an artifact, copied to another environment, or used to start a second job from the same state. The documented purposes are to “stop-and-resume, fork, or update your Flink jobs.” A retained checkpoint can also be used to rescale and, within the limits the documentation lists, to upgrade; what the savepoint adds is ownership, portability, and a format meant to survive those changes, not a monopoly on them.
What it is for in practice
- Rescaling. Changing the parallelism of a stateful job means redistributing state across a different number of workers. Stopping with a savepoint and restarting from it is how that redistribution happens under control rather than as a side effect of a restart.
- Upgrades. New application code, or a new engine version, starting from the state the old one left. This is the case that turns a deployment into a migration, because state written by one version has to be readable by the next.
- Planned maintenance. Stopping cleanly before infrastructure work and resuming afterward, with the position and the state agreeing, rather than relying on failure recovery to do a job it was not designed for. Flink distinguishes an intermediate savepoint, taken while the job keeps running, from stop-with-savepoint, which stops the job once the savepoint is complete; only the latter guarantees that nothing was processed after the snapshot.
- Forking. Starting a second job from the same state โ to test a change against real state, or to run a variant alongside the original. The second job must not share the original’s sinks or transactional identifiers: it writes to outputs of its own, or runs with its external effects disabled, otherwise the two produce duplicate output and overwrite each other’s results. Flink’s documentation notes that running several jobs from one snapshot on the same checkpoint timeline needs particular care with transactional sinks.
State has a schema, and upgrades meet it
The reason an upgrade needs a snapshot to start from rather than a plain redeploy is that a streaming job’s state is structured data with its own compatibility question. Adding a field to an aggregate, changing a key, or replacing an operator changes what the stored state means, and the new version has to be able to read what the old one wrote โ the same compatibility problem that applies to messages and tables, applied to memory that outlives the process. The snapshot by itself settles none of it: operators need stable identifiers so the new job can find its state, and the serializers have to be compatible, which is checked rather than assumed.
Three habits keep this from becoming an incident. Take the savepoint before the change, not after something goes wrong. Keep it until the new version has run long enough to be trusted, since it is the way back to the previous internal state โ and going back re-applies the input processed since it was taken, so that input has to still be available and the sinks have to tolerate writes applied again; restoring state does not roll back output already committed. And test the restore into the new code in a lower environment first โ a savepoint that cannot be read by the version you are deploying is discovered at the worst possible moment otherwise.
How other engines handle the same operations โ rebuilding state from a log, or restarting a query from its checkpoint location โ is worked through in Three Streaming Engines, Three Answers.
Further reading
Discover more from Insightful Data Lab
Subscribe to get the latest posts sent to your email.
