Skip to main content
Flows are saved documents. Somewhere there is a published flow, built months ago, whose nodes were configured against the handler as it existed then — and it is running right now. Node versioning exists so that changing a handler does not reach backwards into those flows.

The rule

The engine resolves a handler by (type, version). An old flow definition names the version it was built against, so it keeps reaching the handler it was designed for, while new flows get the current one.

supportedVersions()

The registry keys handlers by type@version(). supportedVersions() is only validated to contain the handler’s own version and has no runtime effect today. It is usually just the current version:
A handler may list older versions as documentation of what it can handle. This does not make it serve them: the class for version 1 must stay registered for as long as flows reference it.
Listing an older version changes nothing at runtime today, so do not rely on it to keep old flows working. Keep the old handler registered.

What counts as breaking

The test is not “did the code change” but “would a flow configured against the old contract still do what its author meant”. Removing a config field is breaking. Renaming one is breaking. Changing the meaning of an existing value is breaking, even when the field name and type are identical. Adding an optional field with a default is not.

Sessions hold their definition

A running flow session snapshots its flow_definition_id and keeps it until the session finishes. Publishing a new version of a flow therefore does not rewrite what an in-flight conversation is doing — it changes what the next conversation starts with.