Apache Airflow is a platform to programmatically author, schedule, and monitor workflows. You define your pipelines as Python code; Airflow's scheduler then runs your tasks on a pool of workers while honoring the dependencies you declared. A rich web UI lets you visualize pipelines in production, watch progress, inspect logs, and retry or backfill work when something goes wrong.
This guide is written for the people who use Airflow day to day: data engineers and analysts who author DAGs, and operators who trigger, monitor, and troubleshoot runs from the command line or the web interface. It covers installation, core concepts, the complete airflow command-line interface, the everyday tasks you perform against a running environment, and a deep troubleshooting and FAQ reference.
Note
Architecture deep dives, the full
airflow.cfgconfiguration reference, deployment topologies, executor selection, database tuning, and security hardening live in the companion Admin Guide. This guide links there whenever a topic crosses into operations.
1. What Airflow Is (and Is Not)
Airflow orchestrates batch workflows. You express a pipeline as a DAG (Directed Acyclic Graph) — a collection of tasks with directional dependencies — written in Python. The scheduler reads your DAG files, decides which task instances are ready to run, and hands them to an executor, which runs them on workers. Everything that happens is recorded in a metadata database and surfaced in the UI and REST API.
Airflow's design philosophy, taken directly from the project:
- Dynamic — Pipelines are defined in Python, so DAGs can be generated and parameterized in code.
- Extensible — A large library of built-in operators ships in provider packages, and you can write your own.
- Flexible — Airflow leans on the Jinja templating engine for rich, runtime-parameterized commands.
Important
Airflow works best with workflows that are mostly static and slowly changing — where the DAG structure is similar from one run to the next. Tasks should be idempotent (re-running produces the same result without duplicating data) and should not pass large volumes of data between each other. For passing small bits of metadata between tasks, use Airflow's XCom feature; for high-volume data, delegate to an external system (a warehouse, Spark, etc.) and let Airflow orchestrate it.
Caution
Airflow is not a streaming solution. It is frequently used to process near-real-time data by pulling from streams in batches, but it is not an event-by-event stream processor.
Versioning at a glance
Airflow follows strict SemVer. Crucially, core Airflow and each provider version independently: an amazon or google provider release has its own MAJOR/MINOR cycle and can be installed against multiple Airflow versions. The Helm chart and the language API clients also version independently. This guide documents Airflow core 3.3.0.
2. The Airflow Family at a Glance
Airflow is developed as a single repository that ships several separately installed, separately consumed products. As a user you will almost always start with the core platform; the rest are extensions you add when you need them.
| Product | PyPI / artifact | What it is | When you need it |
|---|---|---|---|
| Apache Airflow (core) | apache-airflow |
The scheduler, API server, DAG processor, triggerer, UI, and the airflow CLI |
Always — this is the platform |
| Providers (87 of them) | apache-airflow-providers-* |
Operators, hooks, sensors, transfers, secrets backends, and executors for external systems (AWS, Google, Postgres, Slack, Kubernetes, …) | Whenever a task talks to an external system |
| Task SDK | apache-airflow-task-sdk |
The stable, lightweight authoring API (airflow.sdk) used inside your DAG and task code |
Authoring DAGs against a forward-compatible interface |
| Airflow CLI (remote) | apache-airflow-ctl (airflowctl) |
A standalone client that drives a remote Airflow instance over its REST API | Operating a remote/managed Airflow from your laptop or CI |
| Helm chart | apache-airflow chart |
Production Kubernetes deployment | Running Airflow on Kubernetes (see Admin Guide) |
| Edge SDKs | go-sdk, java-sdk |
Experimental SDKs for running tasks on edge workers in Go and Java/Kotlin | Polyglot/edge task execution (advanced) |
Tip
Most readers only need three of these: core (run the platform), providers (connect to your systems), and the Task SDK (author your DAGs). Start there. The remainder of this guide is organized that way.
3. Quick Start
The fastest way to see Airflow run end to end is the all-in-one standalone command. It initializes a local SQLite metadata database, creates an admin user, and starts the scheduler, the API server (with the UI), the DAG processor, and the triggerer together in one process group.
pip (virtualenv)
# 1. Create and activate a virtual environment (Python 3.10-3.14)
python -m venv airflow-venv
source airflow-venv/bin/activate
# 2. Install Airflow with a known-good constraint set
pip install 'apache-airflow==3.3.0' \
--constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.3.0/constraints-3.10.txt"
# 3. Choose where Airflow keeps its home directory (dags, logs, config, db)
export AIRFLOW_HOME=~/airflow
# 4. Run everything at once
airflow standalone
Docker image
# Pull the official image and run the all-in-one quick start
docker run -it --rm -p 8080:8080 \
apache/airflow:3.3.0 standalone
When standalone finishes booting it prints the generated admin credentials:
standalone | Airflow is ready
standalone | Login with username: admin password: <generated-password>
Open http://localhost:8080 in your browser, log in with those credentials, and you will see the Dags view populated with the bundled example DAGs.
Warning
airflow standaloneis for local exploration and development only. It uses SQLite and a single-process LocalExecutor, neither of which is safe for production. For real deployments, see the Admin Guide's deployment chapter.
Tip
The admin password is written to
$AIRFLOW_HOME/simple_auth_manager_passwords.json.generated. If you lose the printed value, read it from there.
4. Installation
4.1 Requirements
Airflow 3.3.0 is tested against the following. POSIX-compliant operating systems only — on Windows, run Airflow inside WSL2 or a Linux container.
| Component | Supported versions |
|---|---|
| Python | 3.10, 3.11, 3.12, 3.13, 3.14 |
| Platform | AMD64 / ARM64 |
| Kubernetes | 1.30, 1.31, 1.32, 1.33, 1.34, 1.35 |
| PostgreSQL | 14, 15, 16, 17, 18 |
| MySQL | 8.0, 8.4, Innovation |
| SQLite | 3.15.0+ (development/testing only) |
Caution
SQLite and the default LocalExecutor are fine for trying Airflow but must not be used in production. MariaDB is explicitly not tested or recommended. Use PostgreSQL or MySQL for any shared or production environment.
4.2 Installing from PyPI with constraints
Airflow is simultaneously a library (you import it in your DAGs) and an application (you run its services). Because of that dual nature, its dependencies are kept deliberately open in pyproject.toml, which means a bare pip install apache-airflow can occasionally resolve to an unusable combination. The project therefore publishes constraint files — pinned, known-to-work dependency sets — per Airflow version and per Python minor version.
Important
Always install Airflow with a
--constraintURL. The URL encodes both the Airflow version and your Python version. Onlypipis officially supported; Poetry and pip-tools are not.
# Plain core install, Python 3.10
pip install 'apache-airflow==3.3.0' \
--constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.3.0/constraints-3.10.txt"
Successfully installed apache-airflow-3.3.0 ...
4.3 Installing with extras (providers)
"Extras" pull in the provider packages and their dependencies in one step. Specify them in brackets:
# Core + PostgreSQL + Google providers
pip install 'apache-airflow[postgres,google]==3.3.0' \
--constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.3.0/constraints-3.10.txt"
Common extras include postgres, mysql, celery, cncf.kubernetes, amazon, google, microsoft.azure, slack, http, and ssh. You can also install any provider directly:
pip install apache-airflow-providers-amazon
Note
Providers version independently from core. Installing a provider does not change your Airflow version, and you can upgrade a provider without upgrading Airflow.
4.4 First-run setup (manual)
If you are not using standalone, initialize the environment explicitly:
export AIRFLOW_HOME=~/airflow
# Create/upgrade the metadata database schema
airflow db migrate
DB: sqlite:////home/you/airflow/airflow.db
Performing upgrade to the metadata database ...
Database migrating done!
Then start the services you need in separate terminals or as managed processes (see §6, The Components You Run).
4.5 Verifying the install
airflow version
3.3.0
airflow info
airflow info prints a full environment report — Airflow version, Python version, executor, configured paths, installed providers, and system details. Run it first whenever you file a bug report.
5. Core Concepts You Need Before Authoring
You can use most of Airflow knowing just a handful of terms. (Architecture-level internals are in the Admin Guide.)
| Term | Meaning |
|---|---|
| Dag | A workflow: a Python file defining tasks and their dependencies. (Airflow 3 spells it "Dag".) |
| Task | A single unit of work in a DAG — one node in the graph. |
| Operator | A template for a task (e.g. run a Bash command, call a Python function, run a SQL query). Operators come from providers or the standard set. |
| Task instance | A specific run of a task for a specific logical date/run. |
| Dag run | A specific execution of a whole DAG. |
| Sensor | A special task that waits for a condition (a file, a partition, a time) before succeeding. |
| Hook | A reusable interface to an external system (a database, an API), used inside operators. |
| XCom | "Cross-communication" — a small key/value channel for passing metadata between tasks. |
| Connection | Stored, named credentials/endpoints for an external system, referenced by conn_id. |
| Variable | A stored, named runtime value (often JSON), referenced from DAG code. |
| Pool | A concurrency limit shared across tasks, used to cap parallel access to a resource. |
| Asset | A logical data object; DAGs can be scheduled to run when assets are updated (data-aware scheduling). |
| Bundle | A versioned source of DAG files that the DAG processor reads (a "DAG bundle"). |
6. The Components You Run
A production Airflow is several long-running services. As a user you mostly interact with the CLI and UI, but it helps to know what each process does because you start them with the airflow CLI.
| Command | Process | Responsibility |
|---|---|---|
airflow scheduler |
Scheduler | Decides what runs and when; creates DAG runs and schedules task instances |
airflow api-server |
API server | Serves the REST API and the React web UI (FastAPI + uvicorn) |
airflow dag-processor |
DAG processor | Parses DAG files from bundles and writes serialized DAGs to the database |
airflow triggerer |
Triggerer | Runs asynchronous deferrable operators and sensors efficiently |
airflow standalone |
All of the above | One-process quick start for local use |
Note
In Airflow 3 the old
webservercommand is gone — the UI is served byapi-server. DAG parsing has also been split into its owndag-processorservice. If you are migrating from Airflow 2, update your service definitions accordingly.
Minimal manual startup for development:
airflow scheduler &
airflow dag-processor &
airflow triggerer &
airflow api-server --port 8080
7. Authoring Your First DAG
DAGs are Python files placed in your dags folder (default $AIRFLOW_HOME/dags). Author them against the Task SDK (airflow.sdk), the stable public authoring interface.
7.1 A complete example
from __future__ import annotations
import pendulum
from airflow.sdk import DAG, task
from airflow.providers.standard.operators.bash import BashOperator
with DAG(
dag_id="example_etl",
schedule="@daily",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["example", "etl"],
) as dag:
extract = BashOperator(
task_id="extract",
bash_command="echo 'pulling data' && sleep 1",
)
@task
def transform() -> dict:
return {"rows": 42}
@task
def load(payload: dict) -> None:
print(f"loaded {payload['rows']} rows")
# Dependency wiring: extract -> transform -> load
extract >> load(transform())
# Save as $AIRFLOW_HOME/dags/example_etl.py
# Within ~30s the DAG processor parses it and it appears in the UI.
7.2 What the pieces mean
dag_id— Unique name for the DAG. It is how you reference the DAG everywhere in the CLI and UI.schedule— When the DAG runs. Accepts cron strings ("0 6 * * *"), shorthand presets ("@daily","@hourly"),timedeltaobjects, or an asset expression for data-aware scheduling.start_date— The first logical date the scheduler considers.catchup— IfFalse(recommended for most DAGs), Airflow does not run all missed intervals betweenstart_dateand now when you first enable the DAG.tags— Labels for filtering DAGs in the UI.>>— The dependency operator.a >> bmeans "runa, thenb".@task— The TaskFlow decorator: turns a plain Python function into a task, and its return value becomes an XCom automatically passed to downstream tasks.
Tip
Prefer importing from
airflow.sdk(the Task SDK) rather than deep internal modules. The SDK is the supported, forward-compatible surface; internal imports can break between minor releases.
7.3 Validating a DAG before you ship it
# Parse the file and report import errors without scheduling anything
airflow dags list-import-errors
# Run the whole DAG once locally, in-process, for a date — great for development
airflow dags test example_etl 2026-01-01
[2026-01-01T00:00:00+0000] INFO - Marking run <DagRun example_etl @ 2026-01-01> successful
airflow dags test executes the DAG end to end without needing a running scheduler — the single most useful authoring-loop command.
8. The airflow Command-Line Interface
The airflow CLI is your primary control surface. It is organized into command groups (each managing one kind of object) plus a handful of top-level action commands (mostly to start services). This section documents the full user-facing command tree of Airflow 3.3.0.
Note
Every command accepts
-h/--help. Many object commands accept--output(table,json,yaml,plain) so you can pipe results into scripts. Service commands accept--pid,--daemon,--stdout,--stderr, and--log-filefor process management.
8.1 Top-level map
| Group / command | Purpose |
|---|---|
airflow dags |
Manage DAGs (list, trigger, pause, test, inspect) |
airflow tasks |
Manage and test individual tasks |
airflow backfill |
Create and manage backfills |
airflow partitions |
Manage DAG run partition metadata |
airflow assets |
Inspect and materialize assets |
airflow pools |
Manage concurrency pools |
airflow variables |
Manage variables |
airflow connections |
Manage connections |
airflow teams |
Manage teams |
airflow jobs |
Inspect/health-check running jobs |
airflow db |
Database operations (migrate, check, clean) |
airflow config |
View and lint configuration |
airflow providers |
Inspect installed providers and their extensions |
airflow state-store |
Manage task and asset state storage |
airflow db-manager |
Manage externally connected database managers |
airflow connections, airflow variables, airflow pools |
Object management (above) |
airflow scheduler / api-server / triggerer / dag-processor |
Start core services |
airflow kerberos |
Start a Kerberos ticket renewer |
airflow standalone |
Run an all-in-one copy of Airflow |
airflow rotate-fernet-key |
Re-encrypt secrets after a key rotation |
airflow version |
Print the Airflow version |
airflow info |
Print an environment report |
airflow plugins |
Dump information about loaded plugins |
airflow cheat-sheet |
Print a CLI cheat sheet |
8.2 airflow dags — manage DAGs
| Subcommand | What it does |
|---|---|
list |
List all DAGs known to the environment |
details |
Show details for a single DAG |
list-runs |
List the runs of a DAG (filter by state, date) |
list-jobs |
List jobs associated with DAG runs |
list-import-errors |
Show DAG files that failed to parse |
report |
Show a parse-time report of all DAG files |
state |
Show the state of a specific DAG run |
next-execution |
Show the next scheduled run time(s) |
pause |
Pause a DAG (stop scheduling new runs) |
unpause |
Resume a paused DAG |
trigger |
Manually start a new DAG run |
delete |
Delete a DAG and all its metadata |
show |
Render the DAG structure (e.g. to a graph) |
show-dependencies |
Render cross-DAG/asset dependencies |
test |
Execute a DAG run in-process for a date (no scheduler needed) |
reserialize |
Re-serialize all DAGs into the database |
Common examples:
# List DAGs as JSON
airflow dags list --output json
# Trigger a run now, passing a JSON configuration to the run
airflow dags trigger example_etl --conf '{"region": "us-east-1"}'
# Pause / resume
airflow dags pause example_etl
airflow dags unpause example_etl
# Inspect recent runs that failed
airflow dags list-runs --dag-id example_etl --state failed
# When was this DAG going to run next?
airflow dags next-execution example_etl
# airflow dags trigger output
Created <DagRun example_etl @ 2026-06-04T12:00:00+00:00: manual__2026-06-04T12:00:00+00:00, state:queued>
Tip
airflow dags trigger --conf '{...}'passes a run-time configuration dictionary that your tasks read via the runtime context ({{ dag_run.conf }}in templates). This is the standard way to parameterize manual runs.
8.3 airflow tasks — manage and test tasks
| Subcommand | What it does |
|---|---|
list |
List the tasks in a DAG |
state |
Show the state of a single task instance |
failed-deps |
Explain why a task instance is not runnable (which dependencies fail) |
render |
Render a task's templated fields for a date (see the actual command that would run) |
test |
Run a single task instance in-process for a date, without scheduling |
clear |
Clear task instances so they will be re-run |
states-for-dag-run |
Show the state of every task in a given DAG run |
# List tasks in a DAG
airflow tasks list example_etl
# Dry-run a single task for a date (prints logs to your terminal)
airflow tasks test example_etl transform 2026-01-01
# Why is this task stuck?
airflow tasks failed-deps example_etl load 2026-01-01
# See the exact templated command/SQL that would execute
airflow tasks render example_etl extract 2026-01-01
Important
airflow tasks testruns the task immediately and in-process, ignoring dependencies, pools, and the scheduler. It is a development tool — it does not record a normal task instance state the way a scheduled run does.
8.4 airflow backfill — run historical intervals
Backfills run a DAG across a range of past dates. In Airflow 3, backfill is a first-class object you create and manage rather than a flag on dags.
airflow backfill create \
--dag-id example_etl \
--from-date 2026-01-01 \
--to-date 2026-01-31
Note
Use backfills deliberately. They can create many DAG runs at once; combine with pools (§8.6) to cap how much they hit downstream systems.
8.5 airflow connections — manage external credentials
Connections store the endpoints and credentials your operators use, keyed by conn_id.
| Subcommand | What it does |
|---|---|
list |
List stored connections |
get |
Show one connection |
add |
Create a connection |
delete |
Remove a connection |
export |
Export connections to a file (JSON/YAML/env) |
import |
Import connections from a file |
test |
Test that a connection actually works |
create-default-connections |
Seed the default example connections |
# Add a Postgres connection via a connection URI
airflow connections add my_pg \
--conn-uri 'postgresql://user:[email removed]:5432/analytics'
# List and test
airflow connections list --output table
airflow connections test my_pg
# Back up all connections to a file
airflow connections export connections.json
# airflow connections test my_pg
Connection success!
Caution
Connection secrets are encrypted at rest using the Fernet key. Treat exported files (which may contain plaintext credentials) as sensitive and delete them after use. See the Admin Guide's security chapter for secrets backends (Vault, AWS Secrets Manager, etc.).
8.6 airflow pools — limit concurrency
Pools cap how many task instances can run against a shared resource at once.
# Create a pool of 5 slots for a rate-limited API
airflow pools set api_pool 5 "Limit concurrent calls to the vendor API"
# List and inspect
airflow pools list --output table
airflow pools get api_pool
# Import/export pools as JSON
airflow pools export pools.json
airflow pools import pools.json
In a task, assign it to the pool with pool="api_pool".
8.7 airflow variables — runtime values
# Set a JSON variable
airflow variables set feature_flags '{"new_pipeline": true}'
# Get it back (optionally a nested key)
airflow variables get feature_flags
# Bulk import/export
airflow variables export variables.json
airflow variables import variables.json
In a DAG, read it with Variable.get("feature_flags", deserialize_json=True) from the Task SDK.
Tip
Reading a Variable at the top level of a DAG file runs on every parse and hammers the database. Read Variables inside tasks (or use Jinja templating
{{ var.json.feature_flags }}) instead of at module scope.
8.8 airflow assets — data-aware scheduling
| Subcommand | What it does |
|---|---|
list |
List assets known to the environment |
details |
Show details for one asset |
materialize |
Trigger the DAG that produces an asset |
Assets let a DAG be scheduled to run when another DAG updates a dataset, rather than on a clock. Schedule a consumer DAG with schedule=[my_asset].
8.9 airflow config — view configuration
# Print the full effective configuration
airflow config list
# Read a single value
airflow config get-value core executor
# Lint config for deprecated/removed options
airflow config lint
# airflow config get-value core executor
LocalExecutor
Note
By default the API server does not expose configuration in the UI (
expose_config = False) for security. The CLI always reads the local config. The full option reference is in the Admin Guide.
8.10 airflow providers — inspect installed providers
The providers group introspects what each installed provider contributes. Useful subcommands:
| Subcommand | Shows |
|---|---|
list |
All installed providers and versions |
get |
Details for one provider |
hooks |
All hooks registered by providers |
links |
Extra operator links |
widgets |
Connection-form widgets |
behaviours |
Connection-type behaviours |
logging |
Logging handlers contributed |
secrets |
Secrets backends contributed |
executors |
Executors contributed |
notifications |
Notification classes |
configs |
Provider-contributed config |
auth-managers |
Available auth managers |
airflow providers list --output table
airflow providers hooks
8.11 airflow db — database operations
Mostly an operator concern, but two are commonly run by users on dev environments:
# Create/upgrade the schema (run after install and after upgrades)
airflow db migrate
# Verify connectivity and schema health
airflow db check
# Open an interactive DB shell
airflow db shell
# Purge old metadata (use with care — see Admin Guide)
airflow db clean --clean-before-timestamp 2026-01-01
Warning
airflow db clean,db reset, anddb downgradeare destructive.db resetdrops all metadata. Read the Admin Guide before running any of them against a shared environment.
8.12 Other top-level commands
airflow version # Print version (3.3.0)
airflow info # Full environment report (attach to bug reports)
airflow cheat-sheet # Print a quick command cheat sheet
airflow plugins # List loaded plugins
airflow rotate-fernet-key # Re-encrypt secrets after rotating the Fernet key
9. The Web UI
The web interface is served by airflow api-server (default http://localhost:8080). It is the fastest way to observe and intervene in running pipelines.
| View | What it gives you |
|---|---|
| Dags | The list of all DAGs, with toggle to pause/unpause, run counts, and quick actions |
| Grid | A time-by-task grid of a DAG's runs — the workhorse for spotting failures across runs |
| Graph | The DAG's task dependency graph for a single run, color-coded by state |
| Code | The source of a DAG (read-only) |
| Home / Dashboard | Summary statistics and health of the environment |
| Assets | Assets and their producer/consumer dependencies |
| Backfill | Create and watch backfills over a date range |
Typical UI workflow when a task fails:
- Open Grid, find the red (failed) task instance.
- Click it and open Logs to read the traceback.
- Fix the cause (data, connection, code).
- Clear the task instance (or the downstream subtree) to re-run it — equivalent to
airflow tasks clear.
Tip
Clearing a task in the Grid view re-runs it and, by default, its downstream tasks. This is the most common recovery action and mirrors the
airflow tasks clearCLI command.
10. Using Providers
Providers are how Airflow talks to the outside world. Each provider ships operators, hooks, sensors, and sometimes transfers, secrets backends, or executors. Airflow 3.3.0 has 87 providers spanning cloud platforms, databases, messaging, and more.
Pattern for using a provider operator:
from airflow.sdk import DAG
from airflow.providers.amazon.aws.operators.s3 import S3CreateBucketOperator
with DAG(dag_id="s3_example", schedule=None, catchup=False) as dag:
create_bucket = S3CreateBucketOperator(
task_id="create_bucket",
bucket_name="my-airflow-bucket",
aws_conn_id="aws_default", # references a stored Connection
)
The *_conn_id argument points at a Connection you created with airflow connections add. The operator's hook reads that connection to authenticate.
Note
Discover what an installed provider offers with
airflow providers hooks,airflow providers list, and the provider's own documentation. Operators are imported fromairflow.providers.<provider>.....
A small sample of widely used providers:
| Provider | Extra | Representative use |
|---|---|---|
amazon |
[amazon] |
S3, Athena, ECS, EMR, Lambda, Redshift |
google |
[google] |
GCS, BigQuery, Dataflow, Cloud Composer |
cncf.kubernetes |
[cncf.kubernetes] |
KubernetesPodOperator, Kubernetes executor |
postgres / mysql |
[postgres] / [mysql] |
SQL execution, transfers |
http |
[http] |
REST calls and sensors |
slack |
[slack] |
Notifications |
ssh |
[ssh] |
Remote command execution |
standard |
(bundled) | BashOperator, PythonOperator, core sensors |
11. Driving a Remote Airflow with airflowctl
airflowctl (the apache-airflow-ctl package) is a standalone command-line client that operates a remote Airflow instance over its REST API. Unlike the airflow CLI — which must run on a host with the metadata database — airflowctl only needs network access to an API server and an auth token.
pip install apache-airflow-ctl
# Point it at your environment and authenticate
export AIRFLOW_CLI_ENVIRONMENT=prod
airflowctl auth login --api-url https://airflow.example.com --token "$AIRFLOW_CLI_TOKEN"
# Now drive the remote instance
airflowctl dags list
airflowctl dags trigger example_etl
| Environment variable | Purpose |
|---|---|
AIRFLOW_CLI_TOKEN |
API auth token |
AIRFLOW_CLI_ENVIRONMENT |
Named environment to target |
AIRFLOW_CLI_API_RETRIES |
Retry attempts on API failure (default 3) |
AIRFLOW_CLI_API_RETRY_WAIT_MIN |
Min backoff seconds (default 1) |
AIRFLOW_CLI_API_RETRY_WAIT_MAX |
Max backoff seconds (default 10) |
AIRFLOW_CLI_DEBUG_MODE |
Enable verbose debug output |
Tip
Use
airflowctlfrom CI pipelines and operator laptops to manage managed/remote Airflow deployments where you have no shell access to the scheduler host.
12. Common Recipes
12.1 Re-run a failed task and everything after it
airflow tasks clear example_etl \
--task-regex 'transform' \
--downstream \
--start-date 2026-06-01 --end-date 2026-06-04 --yes
12.2 Trigger a parameterized one-off run
airflow dags trigger example_etl --conf '{"full_refresh": true}'
12.3 Promote connections/variables between environments
# On source
airflow connections export conns.json
airflow variables export vars.json
# On target
airflow connections import conns.json
airflow variables import vars.json
12.4 Back up before an upgrade
airflow db export-archived --output-path ./archive # archive old rows first if desired
airflow connections export conns.json
airflow variables export vars.json
airflow pools export pools.json
12.5 Throttle a busy DAG
Assign its expensive tasks to a small pool, then cap the DAG itself with max_active_runs and max_active_tasks in the DAG definition.
13. Troubleshooting
Format: the exact symptom, the cause, the fix, and how to prevent recurrence. These are grounded in real, community-reported issues and Airflow's own error surface.
Error: DAG does not appear in the UI
Cause: The DAG processor hasn't parsed it, or the file has an import error. Solution:
airflow dags list-import-errors
airflow dags reserialize
If the file is valid, confirm it is inside the configured dags folder and that the dag-processor service is running.
Prevention: Run airflow dags test <dag_id> <date> before deploying; keep DAG files importable (no heavy top-level work).
Error: airflow command error: the following arguments are required: ...
Cause: A required positional/option argument was omitted.
Solution: Run the command with -h to see required args, e.g. airflow dags trigger -h.
Prevention: Use --output json and scripted wrappers for repeated commands.
Error: Task stuck in queued or scheduled and never runs
Cause: No worker capacity, an exhausted pool, or a stopped scheduler. Solution:
airflow jobs check --job-type SchedulerJob # is a scheduler alive?
airflow tasks failed-deps <dag_id> <task_id> <date>
airflow pools list # are slots available?
Prevention: Monitor scheduler health (scheduler.enable_health_check, see Admin Guide) and size pools to real capacity.
Error: DAG code syntax highlighting is wrong with f-strings (UI display)
Cause: Known UI rendering quirk in the Code view for some f-string patterns (community issue #67986). It is a display artifact only — execution is unaffected.
Solution: None required; the code runs correctly. Verify with airflow tasks render.
Prevention: N/A — cosmetic.
Error: KubernetesPodOperator fails behind a corporate proxy
Cause: A no_proxy regression in older Kubernetes client versions used by the cncf.kubernetes provider (community issue #67845).
Solution: Upgrade the cncf.kubernetes provider to a build that supports Kubernetes client >=36.0.1.
Prevention: Keep providers current; pin provider versions via constraints.
Error: Deep links redirect to the homepage after login (SimpleAuthManager)
Cause: The next parameter was ignored during auto-login on first visit (community issue #67476).
Solution: Upgrade to a release where the fix is applied; re-navigate to the deep link after authenticating.
Prevention: Keep core current.
Error: Duplicate DAG runs under multiple schedulers (HA)
Cause: A race condition for certain partitioned/asset timetables when running multiple schedulers in high-availability (community issue #68045). Solution: If you observe duplicates, reduce to a single scheduler for the affected timetable or apply the latest patch release. Prevention: Track the fix in your upgrade cadence; test HA timetables before relying on them.
Error: sqlite / "database is locked" or poor concurrency
Cause: Running SQLite (the default) with concurrent tasks.
Solution: Switch database.sql_alchemy_conn to PostgreSQL or MySQL (Admin Guide).
Prevention: Never use SQLite beyond local experimentation.
Error: pip install apache-airflow produces a broken environment
Cause: Installed without constraints, so dependencies resolved to an incompatible set.
Solution: Reinstall with the matching --constraint URL for your Airflow and Python version.
Prevention: Always pass --constraint (see §4.2).
14. Frequently Asked Questions
Q: Which Python versions are supported? Python 3.10 through 3.14 for Airflow 3.3.0.
Q: Can I run Airflow on Windows? Not natively. Use WSL2 or a Linux container. Only Linux is a supported production environment.
Q: What's the difference between airflow standalone and running the services separately?
standalone runs the scheduler, API server, DAG processor, and triggerer together with SQLite and a generated admin user — for local use only. Production runs each service separately against PostgreSQL/MySQL.
Q: Where did airflow webserver go?
In Airflow 3 the UI and REST API are served by airflow api-server. There is no webserver command.
Q: Where did airflow users and airflow roles go?
User/role management is no longer in core. It is provided by the auth manager you configure. The default SimpleAuthManager uses a simple username/password scheme; the FAB provider supplies full RBAC. See the Admin Guide.
Q: How do I pass data between tasks? Small metadata via XCom (TaskFlow return values do this automatically). Large data should be written to external storage and referenced, not pushed through XCom.
Q: How do I parameterize a manual run?
airflow dags trigger <dag_id> --conf '{"key": "value"}', then read {{ dag_run.conf }} (or context["dag_run"].conf) in your tasks.
Q: What is catchup and should I enable it?
catchup=True makes Airflow run every missed interval back to start_date when a DAG is first enabled. Most users set catchup=False and use explicit backfills when they need historical runs.
Q: How do I install operators for AWS / Google / Kubernetes?
Install the relevant provider, e.g. pip install apache-airflow-providers-amazon, or use an extra like apache-airflow[amazon].
Q: What is a "bundle"? A DAG bundle is a versioned source of DAG files that the DAG processor reads. It lets Airflow track which version of your DAG code produced a given run.
Q: How do I test a single task quickly?
airflow tasks test <dag_id> <task_id> <date> runs it in-process and prints logs, without touching the scheduler.
Q: How do I find out what's installed and where?
airflow info prints the full environment report (version, Python, executor, paths, providers).
Q: Why shouldn't I read a Variable at the top of my DAG file? The DAG file is parsed frequently; top-level reads hit the database on every parse. Read Variables inside tasks or via Jinja templating.
Q: How do I drive a remote/managed Airflow without shell access?
Use airflowctl (the apache-airflow-ctl package) against the REST API with a token.
15. Quick Reference
Service commands
| Command | Starts |
|---|---|
airflow scheduler |
Scheduler |
airflow api-server |
REST API + web UI |
airflow dag-processor |
DAG parser |
airflow triggerer |
Deferrable task runner |
airflow standalone |
Everything (local only) |
Most-used object commands
| Command | Action |
|---|---|
airflow dags list |
List DAGs |
airflow dags trigger <id> [--conf JSON] |
Start a run |
airflow dags test <id> <date> |
Run a DAG locally |
airflow dags pause/unpause <id> |
Toggle scheduling |
airflow tasks test <id> <task> <date> |
Run one task locally |
airflow tasks clear <id> ... |
Re-run task instances |
airflow connections add/list/test |
Manage connections |
airflow variables set/get |
Manage variables |
airflow pools set <name> <slots> |
Manage concurrency |
airflow db migrate |
Apply schema migrations |
airflow config get-value <sec> <key> |
Read one setting |
Key environment variables
| Variable | Default | Meaning |
|---|---|---|
AIRFLOW_HOME |
~/airflow |
Root for dags, logs, config, and (default) the SQLite db |
AIRFLOW_CONFIG |
$AIRFLOW_HOME/airflow.cfg |
Path to the config file |
AIRFLOW__<SECTION>__<KEY> |
— | Override any config option via environment (e.g. AIRFLOW__CORE__EXECUTOR) |
AIRFLOW_CLI_TOKEN |
— | Token for airflowctl |
Tip
Any
airflow.cfgsetting can be overridden with an environment variable namedAIRFLOW__SECTION__KEY(double underscores, uppercased). This is the most common way to configure Airflow in containers. The full option list is in the Admin Guide.