<@ULVA73B9P> For a worker that runs in kubernetes,...
# ask-marvin
r
@Marvin For a worker that runs in kubernetes, where is the task cache stored?
m
thought for 166.9 seconds
Short answer: it’s not on the worker. Assuming Prefect 3.x: - In-process cache: Prefect keeps a small LRU cache in memory inside the flow-run process (i.e., the pod that’s executing your flow). This is per-process and disappears when the pod exits; it’s not shared across pods. - Cross-run/task cache lookup: Prefect stores cache metadata (cache_key and expiration) in the Prefect API (Cloud/Server) database. When a task runs, it queries the API for a prior, unexpired result with the same cache_key. - Result payloads: The actual task results are stored wherever you persist them. By default this is the pod’s local filesystem, which is ephemeral in Kubernetes. For cache reuse across pods or runs, configure shared result storage (e.g., S3/GCS/Azure or a PVC) and set
persist_result=True
on the task/flow. Example (shared storage across pods):
Copy code
from datetime import timedelta
from prefect import task, flow
from prefect.tasks import task_input_hash
from prefect.filesystems import RemoteFileSystem

s3_store = RemoteFileSystem(basepath="<s3://my-bucket/prefect-results>")  # ensure creds are available

@task(
    cache_key_fn=task_input_hash,
    cache_expiration=timedelta(days=1),
    persist_result=True,
    result_storage=s3_store,
)
def expensive(x):
    ...

@flow
def main(x):
    return expensive(x)
Net/net: - Worker pods do not hold the cache. - Cache metadata lives in the Prefect API. - Result bytes live in your configured result storage; use shared storage if you want cache hits across different Kubernetes pods.
r
@Marvin If i persist cache and store it - how long is it store for then? And how does the cleanup happen?
m
thought for 94.1 seconds
Great question — there are two different “lifetimes” to consider. 1) Cache validity (when Prefect will reuse it) - Controlled by your task’s
cache_expiration
. - Example:
cache_expiration=timedelta(days=7)
means Prefect will reuse a matching cached result for 7 days. - If you set
cache_expiration=None
, the cache does not expire (it will be reused indefinitely) unless you change the cache key, set
refresh_cache=True
, or the metadata is no longer available (e.g., old run records are purged). 2) Object retention (how long the stored bytes live) - Prefect does not automatically delete results from your storage. - Where they live depends on your `result_storage`: - Pod filesystem: disappears with the pod. - Shared/PVC or cloud storage (S3/GCS/Azure): persists until you delete it. - Cleanup is your responsibility. Use lifecycle/retention policies on your storage (e.g., S3 lifecycle rules) to delete old objects after your desired period. Notes on metadata cleanup: - The Prefect API stores cache metadata (cache_key + expiration) attached to past task runs. After
cache_expiration
passes, Prefect will ignore those entries. - Prefect Cloud may apply workspace data-retention policies that purge old run records, which also removes the metadata needed for cache hits (the objects in your bucket will still remain unless your bucket policy deletes them). - Self-hosted Server does not automatically purge old run records; you’d manage DB retention yourself. Typical setup: - Set
cache_expiration
to your desired TTL for reuse. - Set
persist_result=True
and use shared storage for cross-pod reuse. - Add a storage lifecycle rule to delete objects older than your TTL (plus a buffer). Example:
Copy code
from datetime import timedelta
from prefect import task

@task(
    cache_key_fn=lambda ctx, params: f"{params['x']}",
    cache_expiration=timedelta(days=7),
    persist_result=True,
)
def expensive(x):
    ...
If you want guidance specific to Prefect Cloud vs self-hosted, let me know which you’re using and I can outline concrete cleanup options.