home
diamond Go Premium
Data Engineering Path  ·  Airflow
Apache Airflow Logo

Airflow 3.0: Datasets Become Assets

Same Idea, New Name, More Capability

Airflow 3.0 renamed Dataset to Asset - not just cosmetically. The rename came with real new capability: Assets can now watch for changes in external systems directly, not just wait for an Airflow task to declare an update.

A Note on This Page's Screenshots
This local sandbox runs Airflow 2.10.0. The Datasets page (previous page in this module) shows real screenshots of that same underlying mechanism under its Airflow 2.x name. The code below is correct Airflow 3.x syntax, shown without a live run.

The Rename, in Code

# Airflow 2.x
from airflow.datasets import Dataset
orders_dataset = Dataset("s3://data-lake/orders/daily.csv")

# Airflow 3.x
from airflow.sdk import Asset
orders_asset = Asset("s3://data-lake/orders/daily.csv")

Everything from the Datasets page carries over unchanged conceptually — outlets=[orders_asset] on a producing task, schedule=[orders_asset] on a consuming DAG. Airflow 3 keeps a compatibility shim so Dataset still works as an alias, but new code should use Asset.


What's Actually New: AssetWatchers

In 2.x, a Dataset only updates when an Airflow task explicitly declares it via outlets=. In 3.0, an AssetWatcher can trigger on changes happening outside Airflow entirely — a message landing in a queue, a webhook firing, a file appearing — without any Airflow task needing to run first:

from airflow.sdk import Asset, AssetWatcher
from airflow.providers.amazon.aws.triggers.sqs import SqsSensorTrigger

# Watches an SQS queue directly - no Airflow task publishes this Asset,
# the queue message itself is the update signal
trigger = SqsSensorTrigger(
    sqs_queue="https://sqs.us-east-1.amazonaws.com/123456789012/orders-updated",
)

orders_asset = Asset(
    "s3://data-lake/orders/daily.csv",
    watchers=[AssetWatcher(name="orders-queue-watcher", trigger=trigger)],
)

@dag(schedule=[orders_asset], ...)
def consume_orders_asset():
    ...

This closes a real gap from the Datasets model: previously, if the file landed in S3 via some other process (not an Airflow DAG), there was no clean way to make Airflow react to it without an Airflow task in the loop somewhere. AssetWatchers let the Asset itself watch the outside world.


Asset Aliases and Multi-Asset Outlets

Airflow 3 also allows a task to declare which Assets it updates dynamically, at runtime, rather than only statically in the decorator:

from airflow.sdk import Asset, task

@task(outlets=[Asset("s3://data-lake/orders/daily.csv")])
def extract_and_load(**context):
    # ... does the actual work ...
    # Can also yield additional runtime-determined Asset events:
    from airflow.sdk import AssetEvent
    yield AssetEvent(uri="s3://data-lake/orders/daily.csv", extra={"row_count": 4821})

The extra payload travels with the Asset event and is readable by downstream consumers — useful for passing lightweight metadata (a row count, a data quality flag) alongside the "this changed" signal itself.

Tip
If a project is already on Airflow 2.4+, adopting Datasets now is not wasted work — the upgrade path to Airflow 3's Asset model is a rename plus opt-in new features, not a rewrite.
lock

This content is reserved for Premium Members.

Upgrade to Premium

Entity Details

Create New Item

help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.