Architecture / Dispatchers
Verified against Flow 5.0.0-beta.39
A dispatcher is the process that takes task runs from Flow, runs them and reports how they ended. This page explains the model. To run Flow's Kubernetes dispatcher, see Dispatcher; to build your own, see Write a dispatcher.
Every arrow to core starts at a dispatcher, because dispatchers pull work and core never pushes it; below each one is what it runs, and the dashed arrow is core reading a running task's live log.
Core decides what runs and when; a dispatcher does the running. Any process that implements Flow's published dispatcher contract is a dispatcher. The contract is an HTTP protocol under /dispatcher/v1, versioned apart from the product: register, poll for work, report each start and end, and keep claims alive. How a task runs (its image, command, volumes, resources and placement) belongs to the dispatcher, not to core.
Only the task types template, script, custom, generic, ai, uploadartifact and downloadartifact reach a dispatcher. The engine runs every other type itself, such as approvals, decisions and sleeps. A dispatcher registers the types it runs and is handed only those. It authenticates with a global machine token: see Security.
The contract is the boundary, not the process. A dispatcher runs as its own deployment only where something has to separate it from core:
Otherwise the poll loop can run inside another Java process, through the dispatcher SDK.
| Shape | Built | Where the poll loop runs |
|---|---|---|
| Kubernetes, through Tekton or Jobs | Yes: Flow's Kubernetes dispatcher | Its own image |
| In-process | Yes, through the SDK | A host application that implements the SDK's TaskHandler |
| Docker, for local development | No | — |
| Serverless containers | No | — |
| A warm pool of microVMs | No | — |
Several dispatchers can serve one Flow, each claiming only the types it registered. For example, to give AI tasks their own network zone, remove ai from the first Kubernetes dispatcher's types and run a second one registered only for ai, in its own namespace. A poll can also filter by task or workflow label, but Flow's Kubernetes dispatcher sends no filters.
| Flow's Kubernetes dispatcher | A dispatcher built with the SDK | |
|---|---|---|
| What it is | The boomerangio/flow-service-dispatcher image, built on the SDK |
Your Java code; the SDK (io.boomerang:dispatcher-sdk) registers, polls, renews leases and reports ends |
| Runs a task as | A pod: a Tekton TaskRun (tekton, the default) or a Kubernetes Job (kube-jobs) |
Whatever your TaskHandler does |
| Task types | template, custom, script, ai, uploadartifact and downloadartifact, so generic tasks wait for another dispatcher |
The types it registers |
| Run workspaces | Creates one volume per run | Optional |
| Task logs | Serves live logs once it's given an address core can reach, and uploads each finished log to core | Optional |
A dispatcher can also speak the protocol directly, in any language.
409 TASKRUN_CLAIM_SUPERSEDED.timedout. A dispatcher silent for 7 days loses its registration, and registers again when it returns.succeeded, failed or invalid, with its results and a reason. Five reasons mean the task never ran to an end, and core requeues it with backoff, up to three times: ExceededQuota, StartTimeout, RateLimited, ClusterUnavailable and DispatcherStopping. A failure the dispatcher marks final is never retried; any other follows the task's own retry setting.The contract covers registration, the work and storage queues, start, heartbeat, end, terminate orders, storage release and two optional log routes. These aren't built: