APACHE AIRFLOWAuthoring DAGs

Operators, Sensors & Hooks In Depth

How data engineers make pipelines run themselves — pick a topic on the left and its full breakdown loads here: the mental model, runnable DAGs, the failure modes that wake people at 3am, and the judgment that separates a scheduled script from an orchestrated system.

18 min readTopics chapter readerLevel · Medium
01 · Orientation

What You’ll Master Here

Operators do work. Sensors wait for work to become possible. Hooks are the connection layer both of them sit on. Almost every authoring decision is choosing between those three.

4 min · Topic 1 of 9

Chapter 3 introduced operators, sensors and hooks as three shapes that all become one node in the graph. This chapter is the working detail: the built-in operators you will meet everywhere, how to build and ship your own, why sensors have a completely different cost model, and the constructor rules that quietly break custom operators.

The centrepiece is a full walkthrough of writing a custom operator — where the file goes, what the class looks like, how to make it templated, how to import it, and how to test it. That is the part most Airflow material skips.

Core mental model

Operators do work. Sensors wait for work to become possible. Hooks are the connection layer both of them sit on. Almost every authoring decision is choosing between those three.

Why it matters

The provider ecosystem is Airflow’s real moat — thousands of maintained integrations that already handle auth refresh, pagination and retry semantics. Engineers who do not know it exists rewrite that work badly. Engineers who over-trust it write a custom operator for three lines of Python.

Provider package
A separately versioned package of operators and hooks for one external system. Upgraded independently of Airflow itself.
Hook
The reusable client for an external system. Handles connection lookup and auth; operators are largely thin wrappers over hooks.
Sensor
A subclass of operator whose only job is to wait for an external condition to become true.
BaseOperator
The class every operator inherits from, imported in Airflow 3 as `from airflow.sdk import BaseOperator`.
Before writing an integration, check whether one already exists
SystemProvider packageTypical operator
AWS (S3, EMR, Glue)apache-airflow-providers-amazonS3KeySensor, EmrAddStepsOperator
Google Cloudapache-airflow-providers-googleBigQueryInsertJobOperator, GCSToBigQueryOperator
Azureapache-airflow-providers-microsoft-azureWasbBlobSensor, AzureDataFactoryRunPipelineOperator
Snowflakeapache-airflow-providers-snowflakeSQLExecuteQueryOperator with a Snowflake conn
Postgres / MySQLapache-airflow-providers-postgresSQLExecuteQueryOperator, PostgresHook
Spark / Databricksapache-airflow-providers-databricksDatabricksSubmitRunOperator
Kubernetesapache-airflow-providers-cncf-kubernetesKubernetesPodOperator
dbtapache-airflow-providers-dbt-cloud (or Cosmos)DbtCloudRunJobOperator
Slack / emailapache-airflow-providers-slackSlackWebhookOperator
Bash, Python, emptyapache-airflow (built in)BashOperator, @task, EmptyOperator
Providers are versioned separately from Airflow itself, which is the point — you can upgrade the Snowflake integration without upgrading Airflow. It also means pinning them in requirements is not optional.
Common mistake

Writing a custom integration for a system that already has a provider. You reimplement auth refresh, pagination and retry semantics, and you maintain them forever. The provider version already handles the edge cases you have not met yet.

Better habit

Search the provider list before writing any integration code. It takes a minute and usually ends the task.

Pin provider versions in requirements. They are versioned independently, so “it worked yesterday” is a real failure mode.

Treat waiting as a distinct kind of work with its own resource cost, not as a slow task.

Do, wait, connect

Operators do, sensors wait, hooks connect. Hold that split and the rest of the chapter is detail.

Remember this

Know what already exists before you write anything — then know exactly how to write the thing that does not.