Data engineering
Incremental Order Events Pipeline
- Company
Instacart- Job positions
- Data EngineerAnalytics Engineer
- Topics
- Data pipelinesIncremental loadingDeduplicationData quality testsSQL
The scenario
Instacart: Load raw order events one day at a time into clean tables that stay correct with duplicates, late events and a changing schema.
Instacart's apps send an event every time an order moves forward: placed, shopper assigned, picked and delivered. The events land in storage as one file per day. Analysts keep getting different order counts from the same data, and the operations team wants daily numbers it can trust. You're a data engineer on the fulfillment data team.
Your task
Build a pipeline that loads the daily event files one at a time into clean tables, producing an order table and daily metrics that are correct and do not change when the pipeline runs again.
Instructions
- 1Load the three event files in date order, one run per file, as if each one arrived on its own day. Profile each file before transforming it.
- 2Design a staging layer that keeps every event exactly once, even when the same event is sent twice or arrives in a later file.
- 3Handle the new column that appears in the third file without breaking the earlier loads.
- 4Build a fact_orders table with one row per order: order_id, store_id, order_date (the UTC date of the placed event), placed_at, final_status (delivered, canceled or in_progress) and minutes_to_deliver (from placed to delivered, rounded to 1 decimal place).
- 5Build a daily_order_metrics table with order_date, orders_placed, orders_delivered, orders_canceled and avg_minutes_to_deliver, rounded to 1 decimal place. A day's numbers must update when its late events arrive in a later file.
- 6Make every load safe to run twice: loading the same file again must not change the output tables. Add data tests for unique orders, valid statuses and events in a sensible order.
- 7Write a README that explains how to run the pipeline, the table design and every data problem you found.
Datasets
All files come in one download.
events_2025_10_01.csv
Events delivered on October 1, 2025, in the order they were received.
752 rows · 5 columns · 35 KB
| Column | Type | Description |
|---|---|---|
| event_id | integer | Unique ID of the event. |
| order_id | integer | The order the event belongs to. |
| store_id | integer | The store fulfilling the order. |
| event_type | text | What happened: placed, shopper_assigned, picked, delivered or canceled. |
| event_time | text | When it happened, in UTC. |
Preview the first 5 rowsHide preview
| event_id | order_id | store_id | event_type | event_time |
|---|---|---|---|---|
| 900676 | 40174 | 105 | delivered | 2025-10-01T11:44:28Z |
| 900599 | 40154 | 101 | picked | 2025-10-01T13:54:39Z |
| 900660 | 40170 | 103 | shopper_assigned | 2025-10-01T22:52:29Z |
| 900082 | 40021 | 105 | delivered | 2025-10-01T12:52:36Z |
| 900560 | 40144 | 103 | delivered | 2025-10-01T11:19:55Z |
events_2025_10_02.csv
Events delivered on October 2, 2025.
853 rows · 5 columns · 40 KB
| Column | Type | Description |
|---|---|---|
| event_id | integer | Unique ID of the event. |
| order_id | integer | The order the event belongs to. |
| store_id | integer | The store fulfilling the order. |
| event_type | text | What happened: placed, shopper_assigned, picked, delivered or canceled. |
| event_time | text | When it happened, in UTC. |
Preview the first 5 rowsHide preview
| event_id | order_id | store_id | event_type | event_time |
|---|---|---|---|---|
| 901045 | 40269 | 101 | picked | 2025-10-02T19:10:44Z |
| 901622 | 40417 | 102 | canceled | 2025-10-02T10:02:32Z |
| 901079 | 40278 | 104 | placed | 2025-10-02T11:47:15Z |
| 900871 | 40225 | 106 | picked | 2025-10-02T12:22:02Z |
| 901530 | 40393 | 105 | delivered | 2025-10-02T19:20:53Z |
events_2025_10_03.csv
Events delivered on October 3, 2025. The mobile team started sending the app version this day.
844 rows · 6 columns · 46 KB
| Column | Type | Description |
|---|---|---|
| event_id | integer | Unique ID of the event. |
| order_id | integer | The order the event belongs to. |
| store_id | integer | The store fulfilling the order. |
| event_type | text | What happened: placed, shopper_assigned, picked, delivered or canceled. |
| event_time | text | When it happened, in UTC. |
| app_version | text | Version of the app that sent the event. |
Preview the first 5 rowsHide preview
| event_id | order_id | store_id | event_type | event_time | app_version |
|---|---|---|---|---|---|
| 901042 | 40268 | 102 | delivered | 2025-10-02T19:10:43Z | 5.13.0 |
| 901866 | 40482 | 106 | shopper_assigned | 2025-10-03T16:28:38Z | 5.13.0 |
| 902294 | 40598 | 101 | picked | 2025-10-03T19:00:26Z | 5.13.0 |
| 901760 | 40454 | 101 | shopper_assigned | 2025-10-03T18:23:06Z | 5.12.1 |
| 901933 | 40501 | 101 | placed | 2025-10-03T18:09:21Z | 5.13.0 |
stores.csv
Partner stores that fulfill orders.
6 rows · 3 columns · 1 KB
| Column | Type | Description |
|---|---|---|
| store_id | integer | Unique ID of the store. |
| store_name | text | Store name. |
| city | text | City the store is in. |
Preview the first 5 rowsHide preview
| store_id | store_name | city |
|---|---|---|
| 101 | Greenway Market | Seattle |
| 102 | Harbor Foods | Seattle |
| 103 | Maple Grocery | Chicago |
| 104 | Sunrise Mart | Chicago |
| 105 | Valley Co-op | Austin |
Hints
A later file can hold an event from an earlier day. Decide which day an order belongs to from the event's own timestamp, never from the file it arrived in.
When you combine files in pandas, a column missing from older files is filled with empty values, so the new column does not need special handling there.
events = pd.concat([day_1, day_2, day_3], ignore_index=True)
Deliverable
A public GitHub repo with your pipeline (Python, SQL or dbt), the fact_orders and daily_order_metrics outputs as CSV files, your data tests, and a README explaining how to run it and how it handles duplicates, late events and schema changes.
When you're done, post your repo in the Solutions tab to share it with other learners.
What grading checks
Use this checklist to review your own work before you post and share it.
- Submitted GitHub repo is public and reachable.
- Repo contains pipeline code in Python, SQL or dbt.
- fact_orders output has one row per order with the correct final status and delivery minutes.
- daily_order_metrics output matches the expected counts and averages for every day, including late events.
- Loads are safe to run twice, and the README explains how.
- Data tests cover unique orders, valid statuses and event order.
- README explains how duplicates, late events and the new column are handled.