Jordan Fisher
04/07/2026, 8:16 AMMarvin
04/07/2026, 8:16 AMresearch_prefect_topic
📊 Tools used:
• research_prefect_topic (1x)Jordan Fisher
04/07/2026, 8:55 AMNate
04/07/2026, 1:39 PMMarvin
04/07/2026, 1:39 PMMarvin
04/07/2026, 1:40 PMNate
04/07/2026, 1:40 PMHow does INPUTS task cache policy work under the hood? Does it compute a hash of all the inputs of the task on the task runner and then use that to look up a value in the configured result store (e.g s3). Just checking as my task has very large parameters (e.g image bytes) and I want to make sure there isn't any performance issues.
Marvin
04/07/2026, 1:40 PMMarvin
04/07/2026, 1:44 PMINPUTS - 'param'.
- Prefect first tries JSON serialization with sorted keys; if that fails, it falls back to cloudpickle.
- The serialized bytes are hashed with MD5 (usedforsecurity=False) to make the cache/transaction key.
- Only task inputs are used; flow parameters are not unless you add FLOW_PARAMETERS to your policy.
Where it’s computed
- On the worker, when the task engine enters the transaction for that task run.
- See compute_transaction_key in the task engine: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/task_engine.py#L260-L310
How the lookup works with result stores (e.g., S3)
- The MD5 “transaction key” is used to check existence in the configured ResultStore (local, S3, etc.).
- If present and not expired, the transaction reads the stored result and short-circuits task execution.
- Under the hood, the transaction key points to metadata that includes a separate storage key for the actual result payload.
- Transaction existence check: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/transactions.py#L299-L318
- Result store existence/read details: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/results.py#L590-L631
- Storage key generation (UUID by default): https://github.com/PrefectHQ/prefect/blob/main/src/prefect/results.py#L71-L74
Large parameters (e.g., image bytes) and performance
- Prefect serializes the full inputs to bytes, then hashes them—there’s no truncation or streaming for the cache key.
- For large binaries (tens/hundreds of MB+), expect noticeable CPU and memory overhead due to:
- Building a serialized representation (JSON fails for bytes, so it’ll typically use cloudpickle)
- MD5 over the full serialized byte string
- Recommendation: exclude large payloads from the key and use a lightweight, deterministic surrogate instead (e.g., a content digest, file path, or S3 key).
Practical patterns
- Exclude the heavy param:
from prefect import task
from prefect.cache_policies import INPUTS
@task(cache_policy=INPUTS - 'image_bytes')
def process_image(image_bytes: bytes, model: str, resize: tuple[int, int]):
...
- Pass a small digest alongside the bytes, and only include the digest in the key:
from prefect import task
from prefect.cache_policies import INPUTS
@task(cache_policy=INPUTS - 'image_bytes')
def process_image(image_bytes: bytes, image_digest: str, model: str, resize: tuple[int, int]):
# use image_bytes for work; caching keys off image_digest+model+resize
...
- Or define a custom key policy to control exactly what contributes to the key:
from prefect import task
from prefect.cache_policies import CacheKeyFnPolicy
from prefect.utilities.hashing import stable_hash
def key_fn(task_ctx, inputs, **_):
return stable_hash(
inputs['image_digest'],
inputs.get('model', ''),
str(inputs.get('resize', '')),
)
@task(cache_policy=CacheKeyFnPolicy(key_fn))
def process_image(image_bytes: bytes, image_digest: str, model: str, resize: tuple[int, int]):
...
Notes and edge cases
- Stable transforms: Prefect applies a stabilizing transform for pandas DataFrames (sorts columns) before hashing to keep keys deterministic. https://github.com/PrefectHQ/prefect/blob/main/src/prefect/cache_policies.py#L33-L46
- Non-serializable inputs (locks, file handles, etc.) will raise during hashing; exclude them or use a custom key fn.
- Hashing utilities (JSON-then-pickle fallback and MD5): https://github.com/PrefectHQ/prefect/blob/main/src/prefect/utilities/hashing.py
- INPUTS policy implementation: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/cache_policies.py#L359-L412
DocsMarvin
04/07/2026, 1:44 PM