Prefect is a modern Python workflow orchestration framework designed to turn any Python function into a reliable, observable data pipeline. Unlike legacy orchestrators that require complex YAML DAG specifications, Prefect uses native Python decorators (@flow, @task) to add orchestration capabilities while keeping code testable and intuitive. The framework embraces dynamic, event-driven workflows where tasks map over runtime data, flows pause for human approval, and automations trigger on custom events β all without forcing your logic into rigid graph structures. Prefect's hybrid execution model (client-side task orchestration with server-side tracking) means flows run anywhere β a laptop, Docker container, Kubernetes pod, or cloud function β with full observability into every state transition, retry, and cache hit.
What This Cheat Sheet Covers
This topic spans 16 focused tables and 110 indexed concepts, 99 flashcards. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
A jump-to index of every table row in this cheat sheet.
An interactive map of every table and concept in this topic.
Table 1: Core Decorators and Flow Definition
Everything in Prefect starts with two decorators β @flow wraps a function as an orchestrated workflow and @task marks the discrete units of work inside it. Master these and you understand the whole mental model: parameters are typed and validated at runtime, subflows compose pipelines from smaller flows, and async variants unlock concurrent execution for I/O-bound work.
| Decorator | Example | Description | |
|---|---|---|---|
@flow(name="etl_pipeline")def etl(): ... | β’ Wraps a Python function as an orchestrated workflow β’ creates a flow run when called with full state tracking and observability | ||
@task(retries=3)def extract(): ... | β’ Wraps a function as a discrete unit of work within a flow β’ task runs are client-side, can be retried and cached individually | ||
@flowdef my_flow(param: int): ... | β’ Defines typed inputs to a flow β’ validated at runtime, visible in the UI, and can be overridden per deployment | ||
@taskdef process(data: list): ... | β’ Standard function arguments passed to tasks β’ serialized for caching and logging, used in cache key computation | ||
if __name__ == "__main__": my_flow.serve(name="prod") | β’ Serve a flow as a long-running deployment with an in-process scheduler β’ no separate worker process needed for simple use cases | ||
@flowdef parent(): child_flow() | β’ Calls another flow from within a flow β’ subflow runs are tracked independently with full state inheritance | ||
@flowasync def my_async_flow(): ... | β’ Defines an asynchronous flow β’ allows use of await and async task execution for I/O-bound workflows | ||
@taskasync def fetch_data(): ... | β’ Asynchronous task β’ can be awaited within async flows or executed concurrently with async task runners |