We use cookies

We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

By clicking "Accept", you agree to our use of cookies.
Learn more.

GuidePatternsDAGs

Declarative Workflow Design (DAGs)

Hatchet workflows are designed in a Directed Acyclic Graph (DAG) format, where each task is a node in the graph, and the dependencies between tasks are the edges. This structure ensures that workflows are organized, predictable, and free from circular dependencies.

WORKFLOWTask ATask BTask CTask Dstartdepends on Aparallelparallelfan-outsequential

How DAG Workflows Work

You declare the graph

Define tasks and their dependencies upfront. Hatchet knows the full shape of work before execution begins.

Hatchet executes in order

Tasks run as soon as their parents complete. Independent tasks run in parallel automatically. A worker slot is only assigned when a task is ready to execute, so tasks waiting on parents consume no resources. Each task has configurable retry policies and timeouts.

Results flow downstream

Task outputs are cached and passed to child tasks. If a failure occurs mid-workflow, completed tasks don’t re-run.

Everything is observable

Every task execution is tracked in the dashboard — inputs, outputs, durations, and errors. You can see exactly where a workflow succeeded or failed.

Defining a Workflow

Start by declaring a workflow with a name. The workflow object can declare additional workflow-level configuration options which we’ll cover later.

The returned object is an instance of the Workflow class, which is the primary interface for interacting with the workflow (i.e. running, enqueuing, scheduling, etc).

💡

The Workflow return object can be interacted with in the same way as a task, however, it can only take a subset of options which are applied at the task level.

Defining a Task

Now that we have a workflow, we can define a task to be executed as part of the workflow. Tasks are defined by calling the task method on the workflow object.

The task method takes a name and a function that defines the task’s behavior. The function will receive the workflow’s input and return the task’s output. Tasks also accept a number of other configuration options, which are covered elsewhere in our documentation.

In Python, the task method is a decorator, which is used like this to wrap a function:

The function takes two arguments: input, which is a Pydantic model, and ctx, which is the Hatchet Context object. We’ll discuss both of these more later.

In the internals of Hatchet, the task is called using positional arguments, meaning that you can name input and ctx whatever you like.

For instance, def task_1(foo: EmptyModel, bar: Context) -> None: is perfectly valid.

Building a DAG with Task Dependencies

The power of Hatchet’s workflow design comes from connecting tasks into a DAG structure. Tasks can specify dependencies (parents) which must complete successfully before the task can start.

Accessing Parent Task Outputs

As shown in the examples above, tasks can access outputs from their parent tasks using the context object:

Running a Workflow

You can run workflows directly or enqueue them for asynchronous execution. All the same methods for running a task are available for workflows!

Pre-Determined Pipelines

DAGs naturally model fixed multi-stage pipelines where the sequence of tasks and their dependencies are known before execution. ETL workflows, document processing pipelines, and CI/CD workflows all follow this pattern: each stage depends on the previous, and the overall structure is visible and predictable in the dashboard.

Task ATask BTask CTask DTask Eparallel