<@ULVA73B9P> Using the default cache policy, tasks...
# ask-marvin
n
@Marvin Using the default cache policy, tasks are only cached if the immediate flow parent is retried. However, if I have a flow which launches a subflow, when I retry the parent flow the subflow gets a new flow run id, and its tasks are not cached. I solved this by creating a new cache policy which depends on the task inputs, the task source code and the root flow run id (instead of the parent flow run id as is the default). Is this the correct approach? Are there any more idiomatic solutions?
m
thought for 143.7 seconds
Yes — your understanding is correct, and your custom policy is a reasonable solution. What’s happening with the default policy - In Prefect 3.x,
DEFAULT
is effectively:
INPUTS + TASK_SOURCE + RUN_ID
-
RUN_ID
is based on the immediate flow run context, not the root/root-parent flow run. - So when a parent flow retries and launches a subflow again, that subflow gets a new flow run ID, which changes the cache key for tasks inside it. That means the default behavior is intentionally scoped to the current flow run lineage at the immediate parent level, and it will not naturally reuse caches across subflow re-creation during parent retries. So is your approach correct? Yes. Using a custom cache policy keyed on: - task inputs - task source -
root_flow_run_id
is a sensible way to make cache reuse survive parent-flow retries that recreate subflows. Is it idiomatic? I’d say: yes, when that’s the behavior you want. Prefect gives you composable cache policies specifically so you can tune cache scope. That said, there are two design choices here: 1. Scope cache to one top-level flow execution - Your
root_flow_run_id
approach - Good when you want reuse across retries of the same overall run, but not across separate top-level flow runs 2. Scope cache purely by data/code identity - e.g.
INPUTS
, or
INPUTS + TASK_SOURCE
, or
INPUTS + FLOW_PARAMETERS
- Good when you want reuse across entirely separate flow runs too So the “more idiomatic” answer depends on your intended cache boundary. When your
root_flow_run_id
approach is a great fit
Use it if you want: - cache hits across subflow re-execution during retries - cache isolation between distinct top-level flow runs - deterministic reuse only within one overall orchestration attempt tree That sounds exactly like your use case. Potential simpler alternative If you actually don’t care about isolating cache to a single root run, then a built-in policy may be simpler, such as: -
INPUTS + TASK_SOURCE
- or
INPUTS + FLOW_PARAMETERS
Those can be more idiomatic if cross-run reuse is acceptable. Example:
Copy code
from prefect import task
from prefect.cache_policies import INPUTS, TASK_SOURCE

@task(cache_policy=INPUTS + TASK_SOURCE, persist_result=True)
def my_task(x):
    ...
But this changes semantics: the cache can be reused by later, unrelated flow runs if inputs/source match. Recommended guidance - If you want cache reuse only within retries of one root flow run, your custom
root_flow_run_id
policy is the right approach. - If you want cache reuse across separate runs too, prefer a built-in composition like
INPUTS + TASK_SOURCE
. One thing to watch Be sure
persist_result=True
is enabled, otherwise there’s nothing durable to reuse. Relevant docs / references - Caching concepts: Prefect caching docs - Cache policies API: prefect.cache_policies - Runtime context: prefect.runtime.flow_run If you want, I can help sketch a clean
CacheKeyFnPolicy
for
root_flow_run_id
using Prefect 3.4.9 conventions.