Prefect 3.7.1 Release Notes - Worker Channel and Orchestration Fixes
PrefectHQ shipped Prefect 3.7.1 on May 16, 2026, a point release that ships the first batch of worker channel infrastructure and clears out a stack of orchestration, concurrency, and result data bugs. Anyone running self hosted workers or pinning Python 3.13 should read this one carefully.
The full release notes and downloads are on the GitHub release page. The internal codename for the release is “Don’t touch that dial!”.
Worker channel groundwork
The largest chunk of new code in 3.7.1 is the worker channel pipeline. The release lands the contract and the first client, both authored by the team:
- Worker channel protocol contract in #21859
- Worker channel client with REST fallback in #21885
- Worker cleanup executor in #21895
- Worker work pool snapshot handling in #21898
cancelling_timeout_teardown.v1cleanup handler in #21911
The shape is a typed protocol between worker and API, plus a client that falls back to the existing REST path when the channel is not available. Existing deployments are not forced to opt in yet, but the cleanup executor and the cancelling_timeout_teardown.v1 handler are already wired up so cancelled runs get torn down predictably instead of hanging in a half cancelled state.
Orchestration, concurrency, and result data fixes
The bug fix list is short on cosmetic items and heavy on correctness:
- Flow run suspension at orchestration boundaries was broken in some paths. Fix in #21875.
- Concurrency lease renewal could starve under load. The renewal now runs on a dedicated thread. See #21925.
- Subflows could be duplicated when a process was re executed against the same
flow_run_id. Patched in #21951. COMPLETEDtoCOMPLETEDtransitions that would discard result data are now rejected, see #21956..get()calls against arbitraryState.datain the result data loss rules are now guarded against non dict payloads in #21967.- The
last_adhoc_pulltimestamp in the runner now uses tz awarenow("UTC")to stay consistent with the rest of the code base, fixed in #21961.
If any of these felt like flaky behaviour in 3.7.0, this is the upgrade that quiets them down.
CLI, templating, and default result storage
The release ships a few ergonomics changes that affect day to day work:
- New
deployment_namelogging variable, useful when you correlate logs by deployment rather than by flow run id. PR #21804. - CLI now infers the logs page size from the API response instead of hard coding it. PR #21711.
- A new CLI command for default result storage lands in #21771, with matching documentation in #21774. Server side default result storage is explicitly marked as beta in #21877, so treat it as such.
- A Pydantic aware
tojsontemplate filter is added in #21861. Models serialize via the Pydantic path instead of the stock JSON one. - Default result storage is now cleared when its backing block is deleted, see #21862.
Python 3.13 and internal module moves
Two changes worth calling out for operators on newer Python:
DateTimeis now strictly tz aware on Python 3.13 and above. Naive datetimes will be rejected. PR #21952.- A round of low and medium risk private modules moved under
_internal. See #21879, #21881, and #21880. If your code reached into private paths inprefectfor_result_recordsorutilities/_engine, those imports need updating.
The UI side gets a couple of small fixes too: flow run log downloads from the Prefect UI in #21718, and a trailing slash preserved when redirecting to the V2 UI in #21912.
Upgrade notes
- If you depend on
prefect-github, the extra floor is now>=0.4.2. Bumped in #21946. - On Python 3.13, audit any code paths that pass naive datetimes into Prefect APIs. They will now be rejected.
- If you imported anything under
prefect.*that started with an underscore, expect the import path to have moved under_internal/.
Where to get it
- Release page: https://github.com/PrefectHQ/prefect/releases/tag/3.7.1
- Repository: https://github.com/PrefectHQ/prefect
- Tag:
3.7.1