How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.
Caching refers to the ability of a task run to enter a Completed state and return a predetermined
value without actually running the code that defines the task.
Caching allows you to efficiently reuse results of tasks that may be expensive to compute
and ensure that your pipelines are idempotent when retrying them due to unexpected failure.By default Prefect’s caching logic is based on the following attributes of a task invocation:
the inputs provided to the task
the code definition of the task
the prevailing flow run ID, or if executed autonomously, the prevailing task run ID
These values are hashed to compute the task’s cache key.
This implies that, by default, calling the same task with the same inputs more than once within a flow
will result in cached behavior for all calls after the first.
This behavior can be configured - see customizing the cache below.
Caching requires result persistenceCaching requires result persistence, which is off by default.
To turn on result persistence for all of your tasks use the PREFECT_RESULTS_PERSIST_BY_DEFAULT setting:
prefect config set PREFECT_RESULTS_PERSIST_BY_DEFAULT=true
See managing results for more details on managing your result configuration, and
settings for more details on managing Prefect settings.
To determine whether a task run should retrieve a cached state, Prefect uses the concept of a “cache key”.
A cache key is a computed string value that determines where the task’s return value will be persisted within
its configured result storage.
When a task run begins, Prefect first computes its cache key and uses this key to lookup a record in the task’s result
storage.
If an unexpired record is found, this result is returned and the task does not run, but instead, enters a
Cached state with the corresponding result value.Cache keys can be shared by the same task across different flows, and even among different tasks,
so long as they all share a common result storage location.By default Prefect stores results locally in ~/.prefect/storage/.
The filenames in this directory will correspond exactly to computed cache keys from your task runs.
Relationship with result persistenceTask caching and result persistence are intimately related. Because task caching relies on loading a
known result, task caching will only work when your task can persist its output
to a fixed and known location.Therefore any configuration which explicitly avoids result persistence will result in your task never
using a cache, for example setting persist_result=False.
Cache key computation can be configured through the use of cache policies.
A cache policy is a recipe for computing cache keys for a given task.Prefect comes prepackaged with a few common cache policies:
DEFAULT: this cache policy uses the task’s inputs, its code definition, as well as the prevailing flow run ID
to compute the task’s cache key.
INPUTS: this cache policy uses only the task’s inputs to compute the cache key.
TASK_SOURCE: this cache policy only considers raw lines of code in the task (and not the source code of nested tasks) to compute the cache key.
FLOW_PARAMETERS: this cache policy uses only the parameter values provided to the parent flow run
to compute the cache key.
NO_CACHE: this cache policy always returns None and therefore avoids caching and result persistence altogether.
These policies can be set using the cache_policy keyword on the task decorator.
All cache keys can optionally be given an expiration through the cache_expiration keyword on
the task decorator.
This keyword accepts a datetime.timedelta specifying a duration for which the cached value should be
considered valid.Providing an expiration value results in Prefect persisting an expiration timestamp alongside the result
record for the task.
This expiration is then applied to all other tasks that may share this cache key.
Cache policies can be composed and altered using basic Python syntax to form more complex policies.
For example, all task policies except for NO_CACHE can be added together to form new policies that combine
the individual policies’ logic into a larger cache key computation.
Combining policies in this way results in caches that are easier to invalidate.For example:
from prefect import taskfrom prefect.cache_policies import TASK_SOURCE, INPUTS@task(cache_policy=TASK_SOURCE + INPUTS)def my_cached_task(x: int): return x + 42
This task will rerun anytime you provide new values for x, or anytime you change the underlying code.The INPUTS policy is a special policy that allows you to subtract string values to ignore
certain task inputs:
from prefect import taskfrom prefect.cache_policies import INPUTSmy_custom_policy = INPUTS - 'debug'@task(cache_policy=my_custom_policy)def my_cached_task(x: int, debug: bool = False): print('running...') return x + 42my_cached_task(1)my_cached_task(1, debug=True) # still uses the cache
You can configure custom cache policy logic through the use of cache key functions.
A cache key function is a function that accepts two positional arguments:
The first argument corresponds to the TaskRunContext, which stores task run metadata. For example,
this object has attributes task_run_id, flow_run_id, and task, all of which can be used in your
custom logic.
The second argument corresponds to a dictionary of input values to the task. For example,
if your task has the signature fn(x, y, z) then the dictionary will have keys “x”, “y”, and “z” with corresponding values that can be used to compute your cache key.
This function can then be specified using the cache_key_fn argument on
the task decorator.For example:
from prefect import taskdef static_cache_key(context, parameters): # return a constant return "static cache key"@task(cache_key_fn=static_cache_key)def my_cached_task(x: int): return x + 1
By default, cache records are collocated with task results and files containing task results will include metadata used for caching.
Configuring a cache policy with a key_storage argument allows cache records to be stored separately from task results.When cache key storage is configured, persisted task results will only include the return value of your task and cache records can be deleted or modified
without effecting your task results.You can configure where cache records are stored by using the .configure method with a key_storage argument on a cache policy.
The key_storage argument accepts either a path to a local directory or a storage block.
Cache isolation controls how concurrent task runs interact with cache records. Prefect supports two isolation levels: READ_COMMITTED and SERIALIZABLE.By default, cache records operate with a READ_COMMITTED isolation level. This guarantees that reading a cache record will see the latest committed cache value,
but allows multiple executions of the same task to occur simultaneously.For stricter isolation, you can use the SERIALIZABLE isolation level. This ensures that only one execution of a task occurs at a time for a given cache
record via a locking mechanism.To configure the isolation level, use the .configure method with an isolation_level argument on a cache policy. When using SERIALIZABLE, you must
also provide a lock_manager that implements locking logic for your system.
There are some situations in which multiple tasks need to always run together or not at all.
This can be achieved in Prefect by configuring these tasks to always write to their caches within
a single transaction.
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Prefect","colors":{"primary":"#2D6DF6","light":"#5F92FF","dark":"#2D6DF6"},"logo":{"light":"https://mintcdn.com/prefect-bd373955/2_4m_dDmEdgqK7r9/logos/logo-wordmark-dark.svg?fit=max\u0026auto=format\u0026n=2_4m_dDmEdgqK7r9\u0026q=85\u0026s=076c95a93dbe29192ba9129faefcc878","dark":"https://mintcdn.com/prefect-bd373955/2_4m_dDmEdgqK7r9/logos/logo-wordmark-light.svg?fit=max\u0026auto=format\u0026n=2_4m_dDmEdgqK7r9\u0026q=85\u0026s=46ef25a1069c303ca7d9e24ec801e760","href":"https://www.prefect.io/docs"},"favicon":"https://mintcdn.com/prefect-bd373955/2_4m_dDmEdgqK7r9/logos/favicon.svg?fit=max\u0026auto=format\u0026n=2_4m_dDmEdgqK7r9\u0026q=85\u0026s=c0e62122cb72036e569b2656916a1b33","api":{"playground":{"display":"simple"}},"appearance":{"default":"light","strict":false},"navbar":{"primary":{"type":"github","href":"https://github.com/PrefectHQ/Prefect"}},"footer":{"socials":{"bluesky":"https://bsky.app/profile/prefect.io","github":"https://github.com/PrefectHQ/prefect","linkedin":"https://www.linkedin.com/company/prefect/mycompany","slack":"https://prefect.io/slack","x":"https://x.com/PrefectIO","youtube":"https://www.youtube.com/c/PrefectIO"}},"seo":{"metatags":{"canonical":"https://www.prefect.io/docs"}},"integrations":{"ga4":{"measurementId":"G-8GR5P04T5Y"},"gtm":{"tagId":"GTM-N633BZ8"}},"errors":{"404":{"redirect":false}},"contextual":{"options":["copy","view"],"display":"header"},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"prefect-bd373955","hasAudioNarration":false,"actualSubdomain":"prefect-bd373955","customDomains":[],"gitSource":{"type":"github","owner":"prefecthq","repo":"prefect","deployBranch":"main","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6aebae2be8d23663794098e8","collectionId":"28a32e15-27de-4edf-91c2-0682e8bb6873","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6aebae2be8d23663794098e8"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"ENABLED"},"CONTEXTUAL_FEEDBACK":{"status":"ENABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6aee42ba68213475f1385309","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"default","tag":"API Reference","count":1172},{"language":"default","tag":"Python SDK Reference","count":364},{"language":"default","tag":"Integrations","count":329},{"language":"default","tag":"REST API","count":183},{"language":"default","tag":"Server API","count":181},{"language":"default","tag":"prefect.server","count":148},{"language":"default","tag":"SDK Reference","count":127},{"language":"default","tag":"How-to Guides","count":71},{"language":"default","tag":"models","count":60},{"language":"default","tag":"api","count":39}]},"assistantConfig":{},"basePath":"/docs","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"styles.css","content":"#topbar-cta-button>a>span{background-color:#2d6df6;border-radius:0.25rem}#topbar-cta-button>a{padding:0.5rem 1rem}#topbar-cta-button>a div>span{font-weight:400;letter-spacing:0.4px}#topbar-cta-button>a div>span,#topbar-cta-button>a div>svg{color:#fff}img{filter:none!important}@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700\u0026display=swap\");@import url(\"https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700\u0026display=swap\");body{font-family:\"Inter\", sans-serif}h1,h2,h3,h4,h5,h6{font-family:\"Roboto\", sans-serif}p{font-family:\"Inter\", sans-serif}[role=\"listitem\"] *:last-child:not(.code-block,.link){border-bottom:none!important}.badge{display:table;margin:0 0 1rem;font-family:\"Inter\", sans-serif;font-size:0.6875rem;font-weight:600;line-height:1;letter-spacing:0.02em;text-transform:uppercase;padding:0.35em 0.6em;border-radius:0.375rem;white-space:nowrap}.badge.cloud{color:#fff;background-color:#2d6df6}.badge.cloud::after{content:\"Prefect Cloud\"}"},{"filePath":"assets/code.css","content":".namespace{opacity:0.7}.token.doctype .token.doctype-tag{color:#79c0ff}.token.doctype .token.name{color:#d2a8ff}.token.comment,.token.prolog{color:#8b949e}.token.punctuation,.language-html .language-css .token.punctuation,.language-html .language-javascript .token.punctuation{color:#c9d1d9}.token.property,.token.tag,.token.boolean,.token.number,.token.constant,.token.symbol,.token.inserted,.token.unit{color:#79c0ff}.token.selector,.token.attr-name,.token.string,.token.char,.token.builtin,.token.deleted{color:#79c0ff}.token.plain-text{color:#fafafa}.language-css .token.string.url{text-decoration:underline}.token.operator,.token.entity{color:#79c0ff}.token.operator.arrow{color:#ff7b72}.token.atrule{color:#79c0ff}.token.atrule .token.rule{color:#d2a8ff}.token.atrule .token.url{color:#79c0ff}.token.atrule .token.url .token.function{color:#79c0ff}.token.atrule .token.url .token.punctuation{color:#d4d4d4}.token.keyword{color:#ff7b72}.token.keyword.module,.token.keyword.control-flow{color:#c586c0}.token.function,.token.function .token.maybe-class-name{color:#d2a8ff}.token.regex{color:#a5d6ff}.token.important{color:#ff7b72}.token.italic{font-style:italic;color:#c9d1d9}.token.constant{color:#79c0ff}.token.class-name,.token.maybe-class-name{color:#d2a8ff}.token.console{color:#9cdcfe}.token.parameter{color:#79c0ff}.token.interpolation{color:#79c0ff}.token.punctuation.interpolation-punctuation{color:#569cd6}.token.boolean{color:#ff7b72}.token.property,.token.variable,.token.imports .token.maybe-class-name,.token.exports .token.maybe-class-name{color:#79c0ff}.token.selector{color:#7ee787}.token.escape{color:#7ee787}.token.tag{color:#7ee787}.token.tag .token.punctuation{color:#808080}.token.cdata{color:#808080}.token.attr-name{color:#79c0ff}.token.attr-value,.token.attr-value .token.punctuation{color:#a5d6ff}.token.attr-value .token.punctuation.attr-equals{color:#d4d4d4}.token.entity{color:#79c0ff}.token.namespace{color:#7ee787}.token.operator{color:#94a3b8}pre[class*=\"language-javascript\"],code[class*=\"language-javascript\"],pre[class*=\"language-jsx\"],code[class*=\"language-jsx\"],pre[class*=\"language-typescript\"],code[class*=\"language-typescript\"],pre[class*=\"language-tsx\"],code[class*=\"language-tsx\"]{color:#79c0ff}pre[class*=\"language-css\"],code[class*=\"language-css\"]{color:#a5d6ff}pre[class*=\"language-html\"],code[class*=\"language-html\"]{color:#c9d1d9}.language-regex .token.anchor{color:#dcdcaa}.language-html .token.punctuation{color:#808080}span.language-json .token.punctuation{color:#4b5563}:is(.dark span.language-json .token.punctuation){color:#d1d5db}span.language-json .token.property{color:#0284c7}:is(.dark span.language-json .token.property){color:9cdcfe}span.language-json .token.string{color:#d97706}:is(.dark span.language-json .token.string){color:#ce9178}span.language-json .token.number{color:#16a34a}:is(.dark span.language-json .token.number){color:#b5cea8}.line-highlight.line-highlight{background:#f7ebc6;box-shadow:inset 5px 0 0 #f7d87c;z-index:0}"}],"page":{"pagePath":"v3/concepts/caching","slug":"/v3/concepts/caching","pageMetadata":{"title":"Caching","description":"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.","keywords":["cache","caching","cache key","result caching","memoization","cache policy"],"href":"/v3/concepts/caching"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Caching refers to the ability of a task run to enter a `,_jsx(_components.code,{children:`Completed`}),` state and return a predetermined\nvalue without actually running the code that defines the task.\nCaching allows you to efficiently reuse `,_jsx(_components.a,{href:`/v3/develop/results/`,children:`results of tasks`}),` that may be expensive to compute\nand ensure that your pipelines are idempotent when retrying them due to unexpected failure.`]}),`\n`,_jsx(_components.p,{children:`By default Prefect’s caching logic is based on the following attributes of a task invocation:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`the inputs provided to the task`}),`\n`,_jsx(_components.li,{children:`the code definition of the task`}),`\n`,_jsx(_components.li,{children:`the prevailing flow run ID, or if executed autonomously, the prevailing task run ID`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`These values are hashed to compute the task’s `,_jsx(_components.em,{children:`cache key`}),`.\nThis implies that, by default, calling the same task with the same inputs more than once within a flow\nwill result in cached behavior for all calls after the first.\nThis behavior can be configured - see `,_jsx(_components.a,{href:`/v3/develop/write-tasks#customizing-the-cache`,children:`customizing the cache`}),` below.`]}),`\n`,_jsxs(Warning,{children:[_jsx(_components.p,{children:_jsx(_components.strong,{children:`Caching requires result persistence`})}),_jsxs(_components.p,{children:[`Caching requires result persistence, which is off by default.\nTo turn on result persistence for all of your tasks use the `,_jsx(_components.code,{children:`PREFECT_RESULTS_PERSIST_BY_DEFAULT`}),` setting:`]}),_jsx(CodeBlock,{numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`prefect config set PREFECT_RESULTS_PERSIST_BY_DEFAULT=true`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/v3/develop/results/`,children:`managing results`}),` for more details on managing your result configuration, and\n`,_jsx(_components.a,{href:`/v3/develop/settings-and-profiles`,children:`settings`}),` for more details on managing Prefect settings.`]})]}),`\n`,_jsx(Heading,{level:`2`,id:`cache-keys`,children:`Cache keys`}),`\n`,_jsxs(_components.p,{children:[`To determine whether a task run should retrieve a cached state, Prefect uses the concept of a “cache key”.\nA cache key is a computed string value that determines where the task’s return value will be persisted within\nits configured result storage.\nWhen a task run begins, Prefect first computes its cache key and uses this key to lookup a record in the task’s result\nstorage.\nIf an unexpired record is found, this result is returned and the task does not run, but instead, enters a\n`,_jsx(_components.code,{children:`Cached`}),` state with the corresponding result value.`]}),`\n`,_jsx(_components.p,{children:`Cache keys can be shared by the same task across different flows, and even among different tasks,\nso long as they all share a common result storage location.`}),`\n`,_jsxs(_components.p,{children:[`By default Prefect stores results locally in `,_jsx(_components.code,{children:`~/.prefect/storage/`}),`.\nThe filenames in this directory will correspond exactly to computed cache keys from your task runs.`]}),`\n`,_jsxs(Warning,{children:[_jsx(_components.p,{children:_jsx(_components.strong,{children:`Relationship with result persistence`})}),_jsx(_components.p,{children:`Task caching and result persistence are intimately related. Because task caching relies on loading a\nknown result, task caching will only work when your task can persist its output\nto a fixed and known location.`}),_jsxs(_components.p,{children:[`Therefore any configuration which explicitly avoids result persistence will result in your task never\nusing a cache, for example setting `,_jsx(_components.code,{children:`persist_result=False`}),`.`]})]}),`\n`,_jsx(Heading,{level:`2`,id:`cache-policies`,children:`Cache policies`}),`\n`,_jsxs(_components.p,{children:[`Cache key computation can be configured through the use of `,_jsx(_components.em,{children:`cache policies`}),`.\nA cache policy is a recipe for computing cache keys for a given task.`]}),`\n`,_jsx(_components.p,{children:`Prefect comes prepackaged with a few common cache policies:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`DEFAULT`}),`: this cache policy uses the task’s inputs, its code definition, as well as the prevailing flow run ID\nto compute the task’s cache key.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`INPUTS`}),`: this cache policy uses `,_jsx(_components.em,{children:`only`}),` the task’s inputs to compute the cache key.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`TASK_SOURCE`}),`: this cache policy only considers raw lines of code in the task (and not the source code of nested tasks) to compute the cache key.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`FLOW_PARAMETERS`}),`: this cache policy uses `,_jsx(_components.em,{children:`only`}),` the parameter values provided to the parent flow run\nto compute the cache key.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`NO_CACHE`}),`: this cache policy always returns `,_jsx(_components.code,{children:`None`}),` and therefore avoids caching and result persistence altogether.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`These policies can be set using the `,_jsx(_components.code,{children:`cache_policy`}),` keyword on the `,_jsx(_components.a,{href:`https://reference.prefect.io/prefect/tasks/#prefect.tasks.task`,children:`task decorator`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`customizing-the-cache`,children:`Customizing the cache`}),`\n`,_jsx(_components.p,{children:`Prefect allows you to configure task caching behavior in numerous ways.`}),`\n`,_jsx(Heading,{level:`3`,id:`cache-expiration`,children:`Cache expiration`}),`\n`,_jsxs(_components.p,{children:[`All cache keys can optionally be given an `,_jsx(_components.em,{children:`expiration`}),` through the `,_jsx(_components.code,{children:`cache_expiration`}),` keyword on\nthe `,_jsx(_components.a,{href:`https://reference.prefect.io/prefect/tasks/#prefect.tasks.task`,children:`task decorator`}),`.\nThis keyword accepts a `,_jsx(_components.code,{children:`datetime.timedelta`}),` specifying a duration for which the cached value should be\nconsidered valid.`]}),`\n`,_jsxs(_components.p,{children:[`Providing an expiration value results in Prefect persisting an expiration timestamp alongside the result\nrecord for the task.\nThis expiration is then applied to `,_jsx(_components.em,{children:`all`}),` other tasks that may share this cache key.`]}),`\n`,_jsx(Heading,{level:`3`,id:`cache-policies-2`,children:`Cache policies`}),`\n`,_jsxs(_components.p,{children:[`Cache policies can be composed and altered using basic Python syntax to form more complex policies.\nFor example, all task policies except for `,_jsx(_components.code,{children:`NO_CACHE`}),` can be `,_jsx(_components.em,{children:`added`}),` together to form new policies that combine\nthe individual policies’ logic into a larger cache key computation.\nCombining policies in this way results in caches that are `,_jsx(_components.em,{children:`easier`}),` to invalidate.`]}),`\n`,_jsx(_components.p,{children:`For example:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`6`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prefect `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` task`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prefect.cache_policies `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` TASK_SOURCE`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`INPUTS`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`@task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`cache_policy`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:`TASK_SOURCE`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` +`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` INPUTS`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` my_cached_task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`x`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`int`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` x `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`+`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 42`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`This task will rerun anytime you provide new values for `,_jsx(_components.code,{children:`x`}),`, `,_jsx(_components.em,{children:`or`}),` anytime you change the underlying code.`]}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`INPUTS`}),` policy is a special policy that allows you to `,_jsx(_components.em,{children:`subtract`}),` string values to ignore\ncertain task inputs:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`14`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`14`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prefect `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` task`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prefect.cache_policies `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` INPUTS`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`my_custom_policy `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` INPUTS`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` -`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'debug'`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`@task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`cache_policy`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`my_custom_policy)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` my_cached_task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`x`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`int`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`debug`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`bool`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` False`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'running...'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` x `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`+`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 42`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`my_cached_task(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`my_cached_task(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`debug`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`True`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# still uses the cache`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`cache-key-functions`,children:`Cache key functions`}),`\n`,_jsx(_components.p,{children:`You can configure custom cache policy logic through the use of cache key functions.\nA cache key function is a function that accepts two positional arguments:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The first argument corresponds to the `,_jsx(_components.code,{children:`TaskRunContext`}),`, which stores task run metadata. For example,\nthis object has attributes `,_jsx(_components.code,{children:`task_run_id`}),`, `,_jsx(_components.code,{children:`flow_run_id`}),`, and `,_jsx(_components.code,{children:`task`}),`, all of which can be used in your\ncustom logic.`]}),`\n`,_jsxs(_components.li,{children:[`The second argument corresponds to a dictionary of input values to the task. For example,\nif your task has the signature `,_jsx(_components.code,{children:`fn(x, y, z)`}),` then the dictionary will have keys “x”, “y”, and “z” with corresponding values that can be used to compute your cache key.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`This function can then be specified using the `,_jsx(_components.code,{children:`cache_key_fn`}),` argument on\nthe `,_jsx(_components.a,{href:`https://reference.prefect.io/prefect/tasks/#prefect.tasks.task`,children:`task decorator`}),`.`]}),`\n`,_jsx(_components.p,{children:`For example:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`11`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prefect `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` task`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` static_cache_key`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`context`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`parameters`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # return a constant`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"static cache key\"`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`@task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`cache_key_fn`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`static_cache_key)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` my_cached_task`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`x`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`int`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` x `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`+`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`cache-storage`,children:`Cache storage`}),`\n`,_jsxs(_components.p,{children:[`By default, cache records are collocated with task results and files containing task results will include metadata used for caching.\nConfiguring a cache policy with a `,_jsx(_components.code,{children:`key_storage`}),` argument allows cache records to be stored separately from task results.`]}),`\n`,_jsx(_components.p,{children:`When cache key storage is configured, persisted task results will only include the return value of your task and cache records can be deleted or modified\nwithout effecting your task results.`}),`\n`,_jsxs(_components.p,{children:[`You can configure where cache records are stored by using the `,_jsx(_components.code,{children:`.configure`}),` method with a `,_jsx(_components.code,{children:`key_storage`}),` argument on a cache policy.\nThe `,_jsx(_components.code,{children:`key_storage`}),` argument accepts either a path to a local directory or a storage block.`]}),`\n`,_jsx(Heading,{level:`3`,id:`cache-isolation`,children:`Cache isolation`}),`\n`,_jsxs(_components.p,{children:[`Cache isolation controls how concurrent task runs interact with cache records. Prefect supports two isolation levels: `,_jsx(_components.code,{children:`READ_COMMITTED`}),` and `,_jsx(_components.code,{children:`SERIALIZABLE`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`By default, cache records operate with a `,_jsx(_components.code,{children:`READ_COMMITTED`}),` isolation level. This guarantees that reading a cache record will see the latest committed cache value,\nbut allows multiple executions of the same task to occur simultaneously.`]}),`\n`,_jsxs(_components.p,{children:[`For stricter isolation, you can use the `,_jsx(_components.code,{children:`SERIALIZABLE`}),` isolation level. This ensures that only one execution of a task occurs at a time for a given cache\nrecord via a locking mechanism.`]}),`\n`,_jsxs(_components.p,{children:[`To configure the isolation level, use the `,_jsx(_components.code,{children:`.configure`}),` method with an `,_jsx(_components.code,{children:`isolation_level`}),` argument on a cache policy. When using `,_jsx(_components.code,{children:`SERIALIZABLE`}),`, you must\nalso provide a `,_jsx(_components.code,{children:`lock_manager`}),` that implements locking logic for your system.`]}),`\n`,_jsx(Heading,{level:`4`,id:`recommended-lock-managers-by-execution-context`,children:`Recommended Lock Managers by Execution Context`}),`\n`,_jsx(_components.p,{children:`We recommend using a locking implementation that matches how you are running your work concurrently.`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Execution Context`}),_jsx(_components.th,{children:`Recommended Lock Manager`}),_jsx(_components.th,{children:`Notes`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Threads/Coroutines`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`MemoryLockManager`})}),_jsx(_components.td,{children:`In-memory locking suitable for single-process execution`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Processes`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`FileSystemLockManager`})}),_jsx(_components.td,{children:`File-based locking for multiple processes on same machine`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Multiple Machines`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`RedisLockManager`})}),_jsx(_components.td,{children:`Distributed locking via Redis for cross-machine coordination`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`multi-task-caching`,children:`Multi-task caching`}),`\n`,_jsxs(_components.p,{children:[`There are some situations in which multiple tasks need to always run together or not at all.\nThis can be achieved in Prefect by configuring these tasks to always write to their caches within\na single `,_jsx(_components.a,{href:`/v3/develop/transactions`,children:_jsx(_components.em,{children:`transaction`})}),`.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Caching","description":"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.","keywords":["cache","caching","cache key","result caching","memoization","cache policy"],"href":"/v3/concepts/caching"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Cache keys","slug":"cache-keys","depth":2,"children":[]},{"title":"Cache policies","slug":"cache-policies","depth":2,"children":[]},{"title":"Customizing the cache","slug":"customizing-the-cache","depth":2,"children":[{"title":"Cache expiration","slug":"cache-expiration","depth":3,"children":[]},{"title":"Cache policies","slug":"cache-policies-2","depth":3,"children":[]},{"title":"Cache key functions","slug":"cache-key-functions","depth":3,"children":[]},{"title":"Cache storage","slug":"cache-storage","depth":3,"children":[]},{"title":"Cache isolation","slug":"cache-isolation","depth":3,"children":[]},{"title":"Recommended Lock Managers by Execution Context","slug":"recommended-lock-managers-by-execution-context","depth":4,"children":[]}]},{"title":"Multi-task caching","slug":"multi-task-caching","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/docs/_mintlify/custom/prefect-bd373955/4f3e55fa53d4a575/script.js","/docs/_mintlify/custom/prefect-bd373955/87a13774513287dd/osano.js","/docs/_mintlify/custom/prefect-bd373955/e7b7298d9b02df32/outbound-referrer.js"],"subdomain":"prefect-bd373955","siteName":"Prefect","title":"Caching - Prefect","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-03T16:58:02.210Z","originalFileLocation":"v3/concepts/caching.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"light\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Prefect\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Caching - Prefect\">\u003cmeta data-mint-head property=\"og:description\" content=\"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Prefect\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://www.prefect.io/docs/v3/concepts/caching\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://prefect-bd373955.mintlify.site/docs/_mintlify/api/og/v2?division=Workflows\u0026amp;title=Caching\u0026amp;description=How+Prefect+caching+works%3A+cache+keys%2C+cache+policies%2C+expiration%2C+storage%2C+isolation%2C+and+sharing+cached+results+across+tasks.\u0026amp;theme=ce2957f9cdece17b41396978\u0026amp;signature=e21a6976ad9a60e5823f298c49107dc305e0ef9c227944fd6c9ef1f015474f0d\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Caching - Prefect\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://prefect-bd373955.mintlify.site/docs/_mintlify/api/og/v2?division=Workflows\u0026amp;title=Caching\u0026amp;description=How+Prefect+caching+works%3A+cache+keys%2C+cache+policies%2C+expiration%2C+storage%2C+isolation%2C+and+sharing+cached+results+across+tasks.\u0026amp;theme=ce2957f9cdece17b41396978\u0026amp;signature=e21a6976ad9a60e5823f298c49107dc305e0ef9c227944fd6c9ef1f015474f0d\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/prefect-bd373955/QsizguCJ7nwtgDte/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Prefect\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#2D6DF6\">\u003clink data-mint-head rel=\"canonical\" href=\"https://www.prefect.io/docs/v3/concepts/caching\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/v3/concepts/caching.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://www.prefect.io/#organization\",\"name\":\"Prefect\",\"url\":\"https://www.prefect.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/prefect-bd373955/2_4m_dDmEdgqK7r9/logos/logo-wordmark-dark.svg?fit=max\u0026auto=format\u0026n=2_4m_dDmEdgqK7r9\u0026q=85\u0026s=076c95a93dbe29192ba9129faefcc878\"}},{\"@type\":\"WebSite\",\"@id\":\"https://www.prefect.io/docs#website\",\"name\":\"Prefect\",\"url\":\"https://www.prefect.io/docs\",\"publisher\":{\"@id\":\"https://www.prefect.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://www.prefect.io/docs/v3/concepts/caching#webpage\",\"url\":\"https://www.prefect.io/docs/v3/concepts/caching\",\"name\":\"Caching\",\"description\":\"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\",\"dateModified\":\"2026-11-03T16:58:02.210Z\",\"isPartOf\":{\"@id\":\"https://www.prefect.io/docs#website\"},\"breadcrumb\":{\"@id\":\"https://www.prefect.io/docs/v3/concepts/caching#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://www.prefect.io/docs/v3/concepts/caching#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Workflows\",\"item\":\"https://www.prefect.io/docs/v3/concepts/flows\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Caching\",\"item\":\"https://www.prefect.io/docs/v3/concepts/caching\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://www.prefect.io/docs/v3/concepts/caching#article\",\"headline\":\"Caching\",\"name\":\"Caching\",\"description\":\"How Prefect caching works: cache keys, cache policies, expiration, storage, isolation, and sharing cached results across tasks.\",\"url\":\"https://www.prefect.io/docs/v3/concepts/caching\",\"mainEntityOfPage\":{\"@id\":\"https://www.prefect.io/docs/v3/concepts/caching#webpage\"},\"dateModified\":\"2026-11-03T16:58:02.210Z\",\"keywords\":\"cache, caching, cache key, result caching, memoization, cache policy\",\"publisher\":{\"@id\":\"https://www.prefect.io/#organization\"},\"isPartOf\":{\"@id\":\"https://www.prefect.io/docs#website\"}}]}\u003c/script>","siteName":"Prefect","nav":{"global":null,"tabs":[{"tab":"Getting Started","pages":[{"title":"Getting Started","href":"/v3/get-started"}]},{"tab":"Concepts","pages":[{"title":"Concepts","sidebarTitle":"Overview","icon":"bars","href":"/v3/concepts"},{"group":"Workflows","pages":[{"title":"Flows","href":"/v3/concepts/flows"},{"title":"Tasks","href":"/v3/concepts/tasks"},{"title":"Assets","description":"Assets represent objects your workflows produce.","href":"/v3/concepts/assets"},{"title":"Caching","href":"/v3/concepts/caching"},{"title":"States","description":"Prefect states contain information about the status of a flow or task run.","href":"/v3/concepts/states"},{"title":"Runtime context","href":"/v3/concepts/runtime-context"},{"title":"Artifacts","href":"/v3/concepts/artifacts"},{"title":"Task runners","href":"/v3/concepts/task-runners"},{"title":"Global concurrency limits","href":"/v3/concepts/global-concurrency-limits"},{"title":"Tag-based concurrency limits","href":"/v3/concepts/tag-based-concurrency-limits"}]},{"group":"Deployments","pages":[{"title":"Deployments","sidebarTitle":"Deployments","href":"/v3/concepts/deployments"},{"title":"Schedule flow runs","sidebarTitle":"Schedules","href":"/v3/concepts/schedules"},{"title":"Work pools","href":"/v3/concepts/work-pools"},{"title":"Workers","href":"/v3/concepts/workers"}]},{"group":"Configuration","pages":[{"title":"Variables","href":"/v3/concepts/variables"},{"title":"Blocks","href":"/v3/concepts/blocks"},{"title":"Settings and profiles","href":"/v3/concepts/settings-and-profiles"},{"title":"Prefect server","href":"/v3/concepts/server"},{"title":"Telemetry","sidebarTitle":"Telemetry","href":"/v3/concepts/telemetry"}]},{"group":"Automations","pages":[{"title":"Events","href":"/v3/concepts/events"},{"title":"Automations","href":"/v3/concepts/automations"},{"title":"Define event triggers","sidebarTitle":"Event triggers","href":"/v3/concepts/event-triggers"}]},{"group":"Prefect Cloud","pages":[{"title":"Rate limits and data retention","href":"/v3/concepts/rate-limits"},{"title":"Measure reliability with Service Level Agreements","sidebarTitle":"SLAs","href":"/v3/concepts/slas"},{"title":"Webhooks","href":"/v3/concepts/webhooks"}]}]},{"tab":"How-to Guides","pages":[{"title":"How-to Guides","href":"/v3/how-to-guides"}]},{"tab":"Advanced","pages":[{"title":"Advanced","href":"/v3/advanced"}]},{"tab":"Examples","pages":[{"title":"Examples","href":"/v3/examples"}]},{"tab":"Integrations","pages":[{"title":"Integrations","href":"/integrations/integrations"}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/v3/api-ref"}]},{"tab":"Contribute","pages":[{"title":"Contribute","href":"/contribute"}]},{"tab":"Release Notes","pages":[{"title":"Release Notes","href":"/v3/release-notes"}]}]},"basePath":"","title":"Caching - Prefect","buildId":"dpl_ATnXPMW25DMPUr9VBw6kL6MfBt6T","deploymentId":"dpl_ATnXPMW25DMPUr9VBw6kL6MfBt6T","dynamics":[],"chunks":[]}