Running large workflows can be time-consuming and expensive, especially when tasks have already produced valid outputs in previous runs. Latch provides two ways to avoid recomputing work:
  1. Retry from failed task – ideal for resuming failed runs without changing inputs.
  2. Task-level caching – useful for skipping specific tasks across multiple runs, even when inputs change.
These features help save compute resources, shorten iteration cycles, and speed up debugging.

1. Default: “Retry from Failed Task”

By default, when a workflow fails, the Latch Console provides a Retry from failed task option. This resumes the workflow from the point of failure. Upstream tasks are skipped and their previous outputs are reused. This is ideal when:
  • Your inputs have not changed
  • You fixed a bug in your code and want to re-run without repeating completed steps

2. Custom Caching for Select Tasks

If you want to launch multiple executions with different workflow-level inputs, but avoid re-running certain expensive tasks whose own inputs have not changed (e.g., rebuilding reference genomes), you can enable task-level caching. This lets you persist outputs for those tasks across workflow runs, regardless of changes to unrelated workflow inputs upstream.
import time
from latch import small_task

@small_task(cache=True)
def do_sleep(foo: str) -> str:
    time.sleep(60)
    return foo

Versioning Your Cache

Use cache_version to manually control when caches are invalidated:
@small_task(cache=True, cache_version="0.0.0")
def do_sleep_with_version(foo: str) -> str:
    time.sleep(60)
    return foo
  • Change the version string to invalidate the cache, even if the code has not changed.
  • Keep the same version to preserve cache even if the task body changes.

Caching Rules

A task’s cache is independent of the workflow it’s in, meaning:
  • Caches persist across workflow re-registrations if the task is unchanged.
  • Caches are preserved if the task is reused in a different workflow.
Cache is invalidated when:
  • Task code changes (non-comment)
  • Function name or parameter types change
  • cache_version changes
Cache is preserved when:
  • Task code and signature remain identical (comments don’t count)
  • Task is reused in a new workflow without changes