Scheduled taxi loads with backfills in Kestra
Module 2 of the Data Engineering Zoomcamp: a Kestra flow that loads 1 month of NYC yellow or green taxi trips per run into Postgres. Each run derives its file from the trigger date, loads it into a staging table it truncates first, stamps every row with an md5 unique_row_id over 7 columns, and runs a MERGE that inserts only the rows the target lacks. Cron triggers on the 1st of each month run it, and the same flow backfills the months before the schedule existed. The module runs it locally first, then again into Cloud Storage and BigQuery.
Each run owns a slice of time, not a moment. A flow that reads its month from the trigger date loads the same file on every retry and every backfill, while one that reads the clock loads whatever month it happens to be. The staging table and the key-matched MERGE make the load safe to repeat: rerun January and the target gains 0 rows. The flow also sets a concurrency limit of 1, and the guide to idempotent data pipelines covers the write patterns behind both choices.
To make it yours, break it on purpose. Rerun a finished month and compare row counts. Kill a run between the staging load and the MERGE. Then raise the concurrency limit and backfill a year to see what 2 runs sharing 1 staging table do. Write down each result; the notes are the part of the project that is yours.
"How would you backfill 6 months?" and "what happens if a task runs twice?" are the first follow-ups in a pipeline design round. You can answer both from a flow you have rerun and backfilled, with the row counts before and after. Interviewers know the Zoomcamp, so the failure you caused and the change you made are what they will ask about.

