learn-data-orchestration-with-phoebe / Session 2 of 6
Learn Data Orchestration with Phoebe · Session 2 of 6

From cron to DAG

Last session the clean job fired at 2:30 whether the extracts had finished or not, and twelve mornings a month quietly paid for it. Tonight the guess about duration becomes a fact about completion: every task waits for its upstreams to succeed, and Daybreak's calendar tells the truth for the first time. Fair warning - the truth looks worse before it looks better.

🟢 Easy You know why the punctual pipeline lies 45 min
0-3 · Welcome 3-18 · What a DAG is, and the same ideas everywhere 18-40 · Build-along: turning the dependencies on 40-45 · Q&A
Part 0

Where the artifact stands

Thirty mornings on time, twelve silently wrong, and a crontab that cannot see the difference. Session 1 ended with the diagnosis: "run at 2:30" is a guess about duration standing in for the thing we actually meant, which was "run after the extracts succeed". Tonight we say the second sentence to a scheduler that can enforce it, watch what it costs, and meet the vocabulary twice - once in Airflow's words, once in Dagster's - to prove the ideas belong to no product.

🎫 Clear all three quiz questions to stamp your passport Live = presented in the 45 minutes Self-study = the full depth, after class

★ What you walk out with: the run-after-not-run-at mental shift, the three downstream run states and why "skipped" is the honest one, a two-vocabulary phrasebook (Airflow and Dagster) for one set of concepts, and a simulator calendar where failures finally show up as missing mornings instead of wrong ones.

Part 1 · covers DAGs

Run after, not run at 7 min live

Airflow's docs define the object this whole course orbits: "A Dag is a model that encapsulates everything needed to execute a workflow" - and crucially, it "dictates the order in which they have to run, and which tasks depend on what others". The arrows from session 1's diagram stop being wishful thinking and become configuration.

The same seven tasks - now the arrows are real extract orders extract payments extract inventory clean join aggregate publish dashboard 2:00am - the only clock left no times here - each task runs when its upstreams succeed The clock starts the night. Completion drives everything after. The padding arms race is over.
🔍 Click to zoom - the 2:30/3:00/3:30 appointments are gone; the arrows are now enforced by the scheduler.
Live The contract, and the three downstream truths 4 min ▶

In Airflow you declare the arrows in code, with the >> and << operators: extracts >> clean >> join. That single line replaces every padded minute from session 1. "Run at 2:30" was a guess about how long the extracts take; "run after clean succeeds" is a fact about whether they finished. Facts do not need safety margins.

Once the arrows are enforced, every task downstream of a failure lands in one of three states, and each one is telling you something true:

  • Success - it ran, on inputs that actually existed. The only green worth trusting.
  • Failed - it ran and died. Loud, visible, attributable to a task and a night.
  • Skipped - it never ran, because its upstream did not succeed. Nothing executed on missing input.

Skipped is the state people instinctively read as a defect, and it is the opposite: it is the DAG refusing to do what cron did every night - run anyway on whatever data was lying there. No output beats wrong output.

Real world

Daybreak's clean task now waits for all three extracts. When extract orders dies at 2:04, clean never fires - and neither does anything after it. The 7am dashboard is visibly missing instead of quietly wrong: a store manager sees a gap and picks up the phone, instead of reading yesterday's numbers with today's date and drafting a memo about a trend that does not exist.

Self-study A run is about a night, not just at a time 3 min ▶

There is a second idea hiding in DAG runs, and it will carry session 5 on its back. Airflow's docs: "Each Dag run in Airflow has an assigned 'data interval' that represents the time range it operates in." And the run's logical date "denotes the start of the data interval, not when the Dag is actually executed."

Read that twice, because it quietly changes what a run IS. Under cron, a run was an event: something that happened at 2am. Under a DAG, a run is a claim about a time range: "this run processes Tuesday night's data" - whenever it actually executes. Tonight, or Thursday, or three weeks from now when you discover Tuesday was wrong. The run being ABOUT a night rather than just AT a time is exactly what makes history repairable, and session 5 will spend its whole build-along cashing that in.

Part 2 · covers Dagster

The same ideas everywhere 7 min live

Everything in part 1 sounded like Airflow features. It is not - it is what orchestration IS, and the fastest proof is hearing a second tool say the same things in different words. Dagster calls a unit of data an asset: "a logical unit of data such as a table, dataset, or machine learning model". Different noun, same arrows.

Airflow says The concept Dagster says Dag + tasks, >> and << a workflow with real order job (the runnable unit) the table a task produces a unit of data with lineage asset the Dag's schedule start on a clock interval schedule an event-based trigger start when an event lands sensor learn the middle column once - the outer columns are just accents Dependencies, clocks, events. Two products, one idea set. Switching tools is a vocabulary lesson.
🔍 Click to zoom - the Airflow-to-Dagster phrasebook, with the concept each pair of words is naming.
Live The phrasebook, and picking the starting gun 5 min ▶

Dagster's own one-liners complete the mapping. A schedule is "a way to automate jobs or assets to occur on a specified interval". A sensor is "a way to trigger jobs or assets when an event occurs". Hold those two next to each other, because they are the last decision cron never let you make: WHEN should the night start at all?

  • Schedule - a clock: kick off the run at 2:00am. Right whenever the cadence itself is the contract - "the dashboard covers yesterday, built overnight".
  • Sensor - an event: kick off the run when the source file actually lands. Right whenever the trigger you care about is a THING arriving, not a time passing.

Notice what the sensor version quietly finishes off. Session 1's crontab started extracts at 2:00 hoping the upstream systems had exported by then - one last guess, one last piece of padding. "Run when the file lands" replaces it with the same move part 1 made downstream: an event fact where a clock guess used to be. Inside the DAG, completion drives the order; at the front door, arrival can drive the start.

Self-study What an orchestrator does not fix 3 min ▶

Honest scoping, before the build-along makes it visceral: an orchestrator manages WHETHER and WHEN tasks run. It has no opinion about whether the code inside them is correct. Daybreak's aggregate task carries a logic bug on days 10 through 13, and it will produce wrong numbers under cron, under a DAG, under every lever this course pulls - because on those nights every upstream genuinely succeeded and every dependency was genuinely satisfied. The DAG did its whole job. The code did its job wrong.

What orchestration buys you is that failure becomes visible and recovery becomes cheap: a dead extract shows as failed, its downstream shows as skipped, and nothing publishes on garbage. What it never buys you is correctness of logic. Keep the two ledgers separate - it is the difference between blaming your scheduler and testing your code.

Build-along

Turning the dependencies on ★ 22 min · everyone builds

Same thirty nights, same seeded failures as session 1. One new lever. Watch which numbers it moves, and - just as important - which it does not.

Baseline first: run the month on bare cron and confirm session 1's pair - 30 of 30 mornings on time, 12 of 30 silently wrong. The punctual liar, exactly as you left it.

Flip "DAG dependencies" and read the whole board before reacting. On time falls to 23 of 30. Silently wrong collapses from 12 to 4. Six mornings are now never published, and one is late but right. Look at the calendar: the reds did not get fixed, they got HONEST - failed nights turned into grey missing squares instead of normal-looking wrong ones.

Kill a task - pick an extract - and run tonight's trace. Downstream, clean and everything after it now reads "skipped - upstream did not succeed" instead of running on stale data. Compare that sentence with session 1's trace, where the same night ended in a dashboard that looked exactly like every other morning.

Name the trade out loud, because it is the session: honesty first. Failed nights became loud missing mornings. Nothing retries yet, and nobody is paged yet - a transient 2:04am blip still costs the whole night, and the gap is discovered by a human at 7am. Those are sessions 3 and 6, and now you know exactly why they exist.

About the 4 that will not budge: the four remaining silently-wrong mornings are the days 10-13 aggregate logic bug. Every dependency was satisfied; the code was simply wrong. No scheduler - not this one, not any lever left in the course - can fix code. Watch that number stay put all the way to session 5, where the backfill at least repairs the record.

Homework

Before session 3 15 min

Check yourself

Three questions

1. What does a DAG add that cron structurally cannot?

The DAG "dictates the order in which they have to run, and which tasks depend on what others" - run-after replaces run-at. It makes nothing faster and, as the days 10-13 bug proves all course long, it cannot make code correct.

2. An extract dies at 2:04 and the morning shows clean as "skipped". Why is that a feature?

Skipped is the DAG's honesty: downstream never executed on stale or missing data. Under cron the same night produced a normal-looking dashboard built on yesterday's partition - the expensive kind of failure, because nobody knows to distrust it.

3. A run's logical date is Tuesday, but it executed Thursday. What does that mean?

The logical date "denotes the start of the data interval, not when the Dag is actually executed". A run is a claim about a time range, not just an event at a time - which is exactly what will make history repairable when session 5 reruns old nights.

Answer all three to see your score.

Sources this session stands on

What was covered

✓Apache Airflow docs (3.3.1) · core concepts: DAGsthe Dag definition, order and dependency dictation, declaring dependencies with >> and <<
✓Apache Airflow docs (3.3.1) · DAG Runsthe data interval, and the logical date as the start of the interval rather than the execution moment
✓Dagster docs · conceptsasset, job, schedule, sensor - the same ideas under different names, the scheduler-agnostic proof

Session 2 cheat sheet

Run after, not run atA completion fact replaces a duration guess. The padding arms race ends where the arrows begin.
Three downstream truthsSuccess, failed, skipped. Skipped is honesty: nothing ran on missing input.
The honesty tradeOn time 30/30 to 23/30, silently wrong 12 to 4. Failures became loud missing mornings.
Data intervalA run is ABOUT a time range; the logical date marks the interval, not the execution moment. Session 5 lives here.
Schedule vs sensorClock or event at the front door. "Run when the file lands" kills the last piece of padding.
What a DAG cannot doFix code. Days 10-13 stay wrong in every mode - orchestration makes failure visible, not logic correct.