# Branching — Apache Airflow: Orchestrate Data Pipelines

Source: https://www.geekswithgeeks.com/en/airflow/flow-branching

> Choose one path at run time with @task.branch and rejoin with a suitable trigger rule.

## Only one path runs

A **branch** task returns the `task_id` (or list of IDs) to follow; all other direct downstream paths are **skipped**. Use it for decisions such as "is it a weekday?" or "did new data arrive?". The task that rejoins the paths needs a trigger rule like `none_failed_min_one_success`, because with the default `all_success` it would be skipped when one of its upstream paths was skipped.

## Decide, wait, fan out

Branching, trigger rules, sensors and dynamic mapping let a DAG adapt to the data and the world.

![Four tools: branch, rule, wait, map.](assets/figures/airflow/section-4-map.svg) — Figure 4.1 — Branch, rule, wait and map.

## A weekday branch

I ran this on Airflow 3.0.6 with `airflow dags test report_branch 2026-10-01`. 1 October 2026 is a Thursday, so `weekday_report` ran, `weekend_summary` was skipped, and Airflow logged one downstream task skipped. `logical_date` is available in the task context.

```python
from datetime import datetime

from airflow.sdk import dag, task
from airflow.providers.standard.operators.empty import EmptyOperator

@dag(schedule="@daily", start_date=datetime(2026, 9, 1), catchup=False)
def report_branch():
    @task.branch
    def choose(logical_date=None):
        return "weekday_report" if logical_date.weekday() < 5 else "weekend_summary"

    weekday = EmptyOperator(task_id="weekday_report")
    weekend = EmptyOperator(task_id="weekend_summary")
    done = EmptyOperator(task_id="done", trigger_rule="none_failed_min_one_success")

    choose() >> [weekday, weekend] >> done

report_branch()
```

## Use a clear join task

Always put a join task after branches and give it the right trigger rule. Forgetting this is the classic reason that everything after a branch is mysteriously skipped.

**Quiz:** What happens to the paths not chosen by a branch task?

- [ ] They run anyway
- [x] They are skipped
- [ ] They fail
- [ ] They are deleted from the DAG

*Answer:* They are skipped. Unchosen branches get the skipped state for that run.
