Bird
Raised Fist0
Apache Airflowdevops~5 mins

Why branching handles conditional logic in Apache Airflow - Why It Works

Choose your learning style10 modes available
Introduction
Sometimes workflows need to make choices based on conditions. Branching in Airflow lets you decide which path to follow next, so your tasks run only when they should.
When you want to run different tasks depending on the day of the week.
When you need to skip some steps if a file is missing.
When you want to run a task only if a previous task succeeded.
When you want to send notifications only if errors occur.
When you want to run different data processing pipelines based on input values.
Config File - branching_dag.py
branching_dag.py
from airflow import DAG
from airflow.operators.python import PythonOperator, BranchPythonOperator
from airflow.utils.dates import days_ago
from airflow.operators.dummy import DummyOperator

def choose_branch(**kwargs):
    condition = kwargs['dag_run'].conf.get('run_branch', 'branch_a')
    if condition == 'branch_a':
        return 'task_branch_a'
    else:
        return 'task_branch_b'

def task_a():
    print('Running branch A task')

def task_b():
    print('Running branch B task')

def final_task():
    print('Final task after branching')

default_args = {
    'start_date': days_ago(1)
}

dag = DAG('branching_example', default_args=default_args, schedule_interval=None)

branching = BranchPythonOperator(
    task_id='branching',
    python_callable=choose_branch,
    dag=dag
)

task_branch_a = PythonOperator(
    task_id='task_branch_a',
    python_callable=task_a,
    dag=dag
)

task_branch_b = PythonOperator(
    task_id='task_branch_b',
    python_callable=task_b,
    dag=dag
)

join = DummyOperator(
    task_id='join',
    trigger_rule='none_failed_or_skipped',
    dag=dag
)

branching >> [task_branch_a, task_branch_b] >> join

This DAG shows how branching works in Airflow.

choose_branch decides which branch to run based on a parameter.

BranchPythonOperator runs this decision function.

task_branch_a and task_branch_b are the two possible paths.

DummyOperator join waits for whichever branch runs to finish before continuing.

Commands
This command starts the DAG and tells it to run branch A by passing a configuration parameter.
Terminal
airflow dags trigger branching_example --conf '{"run_branch": "branch_a"}'
Expected OutputExpected
{"dag_run_id": "manual__2024-06-01T00:00:00+00:00", "state": "running"}
→
--conf - Pass JSON configuration to the DAG run
Lists all tasks in the DAG so you can see the branching and other tasks.
Terminal
airflow tasks list branching_example
Expected OutputExpected
branching join task_branch_a task_branch_b
Runs the branching task alone for the given date to see which branch it chooses.
Terminal
airflow tasks test branching_example branching 2024-06-01
Expected OutputExpected
Running choose_branch [2024-06-01 00:00:00,000] {python_operator.py:114} INFO - Done. Returned value was: task_branch_a
Runs the branch A task alone to verify it works when chosen.
Terminal
airflow tasks test branching_example task_branch_a 2024-06-01
Expected OutputExpected
Running branch A task [2024-06-01 00:00:00,000] {python_operator.py:114} INFO - Done. Returned value was: None
Key Concept

Branching lets your workflow choose different paths based on conditions, so only the right tasks run.

Common Mistakes
Returning a task ID that does not exist in the DAG from the branching function.
Airflow will fail because it cannot find the task to run next.
Always return a valid task ID defined in the DAG from the branching function.
Not using a join or downstream task after branching.
The DAG may end prematurely or not continue properly after branches finish.
Use a DummyOperator or other task to join branches and continue the workflow.
Summary
BranchPythonOperator runs a function that decides which task to run next based on conditions.
You define multiple tasks for different branches and return the chosen task's ID from the function.
Use a join task to wait for whichever branch runs before continuing the workflow.

Practice

(1/5)
1. What is the main purpose of branching in Airflow workflows?
easy
A. To choose which tasks run based on conditions
B. To run all tasks in parallel
C. To schedule tasks at fixed intervals
D. To retry failed tasks automatically

Solution

  1. Step 1: Understand branching concept

    Branching allows workflows to decide which path to take based on conditions.
  2. Step 2: Compare with other options

    Running all tasks in parallel or scheduling are different features, not branching.
  3. Final Answer:

    To choose which tasks run based on conditions -> Option A
  4. Quick Check:

    Branching = Conditional path selection [OK]
Hint: Branching picks one path based on condition [OK]
Common Mistakes:
  • Confusing branching with parallel execution
  • Thinking branching schedules tasks
  • Assuming branching retries tasks
2. Which Airflow operator is used to implement branching logic?
easy
A. PythonOperator
B. DummyOperator
C. BashOperator
D. BranchPythonOperator

Solution

  1. Step 1: Identify branching operator

    The BranchPythonOperator is designed to choose the next task based on a Python function's return value.
  2. Step 2: Eliminate other operators

    PythonOperator runs Python code but does not branch; DummyOperator is a placeholder; BashOperator runs shell commands.
  3. Final Answer:

    BranchPythonOperator -> Option D
  4. Quick Check:

    Branching operator = BranchPythonOperator [OK]
Hint: BranchPythonOperator controls conditional task flow [OK]
Common Mistakes:
  • Choosing PythonOperator instead of BranchPythonOperator
  • Confusing DummyOperator as branching
  • Using BashOperator for branching
3. Given this BranchPythonOperator function, which task will run next?
def choose_task():
    if 5 > 3:
        return 'task_a'
    else:
        return 'task_b'
medium
A. task_b
B. Both task_a and task_b
C. task_a
D. No task runs

Solution

  1. Step 1: Evaluate the condition in the function

    5 > 3 is True, so the function returns 'task_a'.
  2. Step 2: Understand branching behavior

    Only the task returned by the function runs; others are skipped.
  3. Final Answer:

    task_a -> Option C
  4. Quick Check:

    Condition true -> task_a runs [OK]
Hint: Return task name to run next [OK]
Common Mistakes:
  • Thinking both tasks run
  • Choosing task_b despite condition
  • Assuming no task runs
4. What is wrong with this BranchPythonOperator function?
def choose_task():
    if x > 10:
        return 'task_x'
    else:
        return 'task_y'
medium
A. Variable x is not defined, causing an error
B. The function does not return a task id
C. BranchPythonOperator cannot return strings
D. The else block is missing

Solution

  1. Step 1: Check variable usage

    The variable x is used but not defined anywhere in the function or globally.
  2. Step 2: Understand error cause

    Using an undefined variable causes a NameError at runtime.
  3. Final Answer:

    Variable x is not defined, causing an error -> Option A
  4. Quick Check:

    Undefined variable = runtime error [OK]
Hint: Check all variables are defined before use [OK]
Common Mistakes:
  • Assuming missing else block causes error
  • Thinking BranchPythonOperator can't return strings
  • Ignoring undefined variable errors
5. You want to run task_a if a file exists, otherwise run task_b. Which BranchPythonOperator function correctly implements this?
hard
A. def choose(): if os.path.exists('/path/file'): print('task_a') else: print('task_b')
B. def choose(): if os.path.exists('/path/file'): return 'task_a' return 'task_b'
C. def choose(): if os.path.exists('/path/file'): return ['task_a', 'task_b'] else: return 'task_b'
D. def choose(): if os.path.exists('/path/file'): return 'task_b' else: return 'task_a'

Solution

  1. Step 1: Check condition and return values

    def choose(): if os.path.exists('/path/file'): return 'task_a' return 'task_b' returns 'task_a' if file exists, else 'task_b', matching the requirement.
  2. Step 2: Identify errors in other options

    def choose(): if os.path.exists('/path/file'): return 'task_b' else: return 'task_a' reverses tasks; def choose(): if os.path.exists('/path/file'): return ['task_a', 'task_b'] else: return 'task_b' returns a list which is invalid; def choose(): if os.path.exists('/path/file'): print('task_a') else: print('task_b') prints instead of returning task id.
  3. Final Answer:

    def choose(): if os.path.exists('/path/file'): return 'task_a' return 'task_b' -> Option B
  4. Quick Check:

    Return correct task id based on condition [OK]
Hint: Return one task id string, not list or print [OK]
Common Mistakes:
  • Returning list of tasks instead of single task
  • Printing task names instead of returning
  • Swapping task names in condition
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard