Why Apache Airflow Instead of Cron? A Deep Dive Into How Airflow Actually Schedules Your DAGs

2026年8月12日1 次浏览来源:Dev.to阅读原文

"Why not just use a cron job?" is the first question I get whenever someone sees an Airflow DAG.

Fair question.

Cron works.

It's been around for decades.

It's simple.

The real answer isn't that cron is bad — it's that cron solves a different problem than Airflow does.

Cron is a job scheduler.

It runs a command at a fixed time.

That's it.

It doesn't know whether the command succeeded, whether its dependencies are satisfied, or whether it should even run at all today.

It just fires the command and moves on.

Airflow is a workflow orchestrator.

It doesn't just schedule tasks — it models them as a graph of dependencies, tracks their state, retries failed ones, and gives you a UI to see what ran, what failed, and why.

Here's where that difference actually matters.

The problem cron can't solve Imagine a simple ETL pipeline: Extract raw data from an API Validate and clean it Load into a warehouse Run a transformation Send a Slack alert if anything fails With cron, you'd write five separate cron entries, one per step, and hope the timing works out.

If step 2 fails but step 3 runs anyway, you now have bad data in your warehouse.

If step 4 takes twice as long one day, you've silently broken your SLA.

Nobody gets notified unless you manually add alerting logic to every script.

With Airflow, you model this as a DAG: Airflow guarantees the order.

If fails, and never run.

You get automatic retries, failure alerts, and a web UI that shows exactly where the pipeline broke and why.

How Airflow actually schedules a DAG This is where it gets interesting.

Airflow doesn't just "run your Python script at a fixed time" the way cron does.

When you define a DAG with a (or in older versions), Airflow doesn't pass that cron expression directly to the OS scheduler.

Instead, it converts it into a timetable — an internal object that determines when a DAG run should be created.

The scheduler process runs continuously, checking every few seconds whether any DAGs are ready to run based on their timetable.

When a DAG is due, the scheduler creates a DagRun object for that execution date and queues up the tasks.

The actual execution happens on worker processes (via the executor you've configured — Local, Celery, or Kubernetes), not directly from the scheduler itself.

This matters for two reasons:

1.

Airflow schedules based on data intervals, not wall-clock time.

A DAG with (daily at 6 AM) doesn't run at 6 AM to process data at that moment.

It runs at 6 AM to process data for the previous interval — typically yesterday, if you're on a daily schedule.

Airflow's is the start of the data interval, not the time the task actually runs.

This is why (the default in older Airflow versions) can surprise you: if you deploy a new daily DAG on January 10th with a start date of January 1st, Airflow will immediately create DagRuns for every day from Jan 1–9 and try to backfill them all, because it thinks you're behind on processing those intervals.

2.

The scheduler is stateful and centralized.

Unlike cron, which runs independently on each machine, Airflow's scheduler is a single process (or a small cluster in HA setups) that maintains a global view of all DAGs, their schedules, and their current state.

It knows which tasks are running, which are queued, which have failed, and which are blocked by upstream dependencies.

This is what enables features like automatic retries, SLA monitoring, and the ability to pause or unpause a DAG from the UI without touching the server.

The part that actually matters in production The real difference isn't features — it's what happens when things go wrong.

Cron jobs fail silently.

Logs are scattered across servers.

Backfilling a missed run means manually re-running scripts in the right order.

Scaling to 50+ pipelines means managing hundreds of crontab entries across multiple machines, with no central visibility into what's running or what's broken.

Airflow tracks everything — task state, execution history, retry counts, SLAs.

You can backfill a

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools