Define a task that returns a list (or list of dicts) from its execute method or via XCom; this task acts as the source of the mapping
Call .expand() or .expand_kwargs() on the downstream task operator, passing the XCom return value of the upstream task as the mapped argument
Set max_active_tis_per_dag or max_active_tis_per_dagrun on the mapped task to limit parallelism and avoid overwhelming downstream systems
Run the DAG and observe in the Grid view that the mapped task appears as an array of mapped task instances indexed by their position in the input list
Handle partial failures by checking the mapped task's map_index in the downstream task and implementing appropriate retry or skip logic
Known gotchas
The total number of mapped task instances is materialized at runtime just before the mapped task runs; very large lists (thousands of items) create that many task instance rows in the Airflow database, which can degrade the scheduler and UI performance
Dynamic task mapping is available from Airflow 2.3 onward; using it with the classic SubDagOperator pattern or with traditional Airflow 1.x DAGs is not supported
Cross-mapping (expanding over multiple independent arguments) produces a Cartesian product of task instances; unintentional cross-mapping of two lists of length N each produces N-squared tasks
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp