Partitioned reprocessing, replays, late-arriving data, and time travel, so you can reprocess without double-counting.
⏱ 20 min readTopics chapter readerLevel · Building & Orchestration
01 · Orientation
What You'll Master Here
Think in partitions. Process new partitions incrementally; reprocess old partitions to backfill or fix; replace a partition when late data lands. Idempotency makes every reprocess safe.
⏱ 6 min · Topic 1 of 8
August is short. A currency bug shipped eleven days ago, so eleven days of numbers are wrong and the rest are fine. Fixing them means running a pipeline you wrote for "today" over dates in the past — without touching the days that were already correct.
That is this chapter: incremental processing (do only the new work each run) and backfilling (redo old work on purpose). Both rest entirely on the idempotency from Chapter 11 — if a re-run is not safe, none of this is available to you.
The unifying concept is the partition: a named slice of data, almost always a time window like a single day. Partitions are the unit you process incrementally, the unit you reprocess in a backfill, and the unit you replace when late data arrives. Once you think in partitions, incremental runs and backfills stop being scary and become routine.
By the end you will be able to design a pipeline that processes only what changed, backfill a range of history safely without double-counting, and handle late-arriving data without corrupting past results. These are the operations that separate a pipeline you can confidently change from one nobody dares touch.
Core mental model
Think in partitions. Process new partitions incrementally; reprocess old partitions to backfill or fix; replace a partition when late data lands. Idempotency makes every reprocess safe.
Why it matters
Pipelines are not write-once: requirements change, bugs are found, data arrives late. The ability to reprocess history safely is what lets a pipeline evolve. Without it, every fix is a terrifying manual operation; with it, correcting the past is a single, safe command.
partition
A named slice of a dataset, usually a time window (e.g. one day), processed as a unit.
incremental processing
Processing only the new or changed data each run, not the whole history.
backfill
Re-running the pipeline over past partitions to populate or correct history.
late-arriving data
Events that show up after the partition they belong to was already processed.
Rerun, backfill, catchup — three different problemsSix situations. Candidates use these three words interchangeably; interviewers do not.0 of 6 answered
Last night’s run failed on a network blip. Today’s numbers are missing.
A currency conversion has been wrong since 3 January. It is now 14 March.
The scheduler was down from Wednesday to Friday. It is back on Saturday.
A new column was added to the model. Every historical row needs it populated.
A DAG was paused for a week during a migration and has just been unpaused.
Yesterday’s partition is complete, but four events for it arrived this morning.
Common mistake
Designing a pipeline that can only ever process "now" going forward. When a bug is found or logic changes, there is no safe way to fix history; the past stays wrong.
Better habit
Partition data (usually by time) as the unit of processing.
Make every partition reprocessable and idempotent.
Plan for backfills and late data from the first design.
The big idea
Partitions plus idempotency turn "reprocessing the past" from a dangerous one-off into a routine operation. Design for reprocessing and you can change a pipeline without fear.
How to study this chapter
Learn partitions first, then incremental processing, then backfills and late data. Notice that all three rest on the same foundation: an idempotent, partition-scoped run.
Remember this
Incremental processing and backfills both operate on partitions and rely on idempotency; thinking in reprocessable partitions is what lets a pipeline safely evolve and correct its history.
Practice2 prompts
Define a partition and give a typical example.
Explain why a pipeline must be able to reprocess the past, not just go forward.
02 · The framework
Partitions: The Unit of Reprocessing
A partition is a drawer in a filing cabinet, usually one per day. You can open, refill, or replace one drawer without disturbing the others. That independence is the whole point.
⏱ 6 min · Topic 2 of 8
A partition is a named, independent slice of a dataset, and in pipelines it is almost always a time window: one day, one hour. Partitioning by date means each day’s data lives in its own logical bucket that can be read, written, and replaced on its own, without touching any other day.
This independence is the key property. Because 2026-06-03 is a self-contained partition, you can reprocess just that day, fix just that day, or overwrite just that day, while every other day stays untouched. Combine partition-scoped processing with the partition-overwrite idempotency from Chapter 9, and reprocessing any single partition becomes a safe, identical replacement.
Partitioning also drives performance: a query for "yesterday" reads only yesterday’s partition, not the whole table (partition pruning). But for this chapter the crucial role is operational, the partition is the unit you process incrementally, the unit you backfill, and the unit you replace for late data. Everything else in the chapter builds on it.
Core mental model
A partition is a drawer in a filing cabinet, usually one per day. You can open, refill, or replace one drawer without disturbing the others. That independence is the whole point.
Why it matters
Without partitions, "fix Tuesday’s data" means reprocessing everything and hoping nothing else changes. With partitions, it means replacing one independent slice. Partitioning is what makes incremental processing and safe backfills possible at all.
partition key
The column that defines partitions, usually a date (event_date) or hour.
partition independence
The property that one partition can be processed or replaced without affecting others.
partition pruning
Skipping irrelevant partitions in a query, reading only the ones needed.
partition overwrite
Replacing a single partition wholesale, the idempotent way to reprocess it.
Marlow's orders · 146M rows a yearFiner partitions prune better and cost more metadata. Both directions have a floor.365 partitions a year
Granularity
Partition column
what
value
partitions in a year
365
rows in one partition
400,000
size of one partition
72 MB
files after a year, four writers
1,460
scanned by “yesterday”
72 MB
a rerun of one day rewrites
1 partition — 400,000 rows
Daily: one day is one partition, and a partition is ~72 MBThe partition is the unit of reprocessing. Everything else in this chapter — incremental loads, backfills, late data — assumes you can rewrite one of these on its own, and that assumption is made or broken here.
Partitioned on event timeA row goes in the partition for when it HAPPENED. Reports are correct and stable, and a late arrival reopens a partition you had already declared finished — which is why this choice is what makes the late-data topic necessary.
Common mistake
Storing data unpartitioned in one giant table. You cannot reprocess or fix a slice without rewriting everything, making backfills risky and slow.
Choosing a partition key with no operational meaning. Reprocessing does not line up with how you actually fix data (usually by date), losing the independence benefit.
Better habit
Partition by a time key that matches how you reprocess (usually date).
Treat each partition as independently replaceable.
Pair partitioning with partition-overwrite for idempotent reprocessing.
Interview note
Saying "I partition by date so I can reprocess a single day idempotently by overwriting its partition" connects partitioning, idempotency, and backfills in one sentence, exactly the integrated thinking interviewers look for.
Remember this
A partition is an independent slice of data (usually one day) that can be processed or replaced on its own; it is the unit of incremental processing, backfills, and late-data handling.
Practice2 prompts
Explain how date partitioning lets you fix one day without touching others.
Describe how partition-overwrite makes reprocessing a day idempotent.
03 · Forward
Incremental Processing
Incremental = "do only the new work". Append new partitions for immutable data; merge changed records for mutable data. Efficient, but it carries state you must get right.
⏱ 6 min · Topic 3 of 8
Incremental processing means each run handles only the new or changed data, not the entire history. A daily pipeline processes today’s partition; it does not recompute all of last year every night. This is the difference between a pipeline that stays fast as data grows and one that gets slower until it no longer fits its window.
There are two flavours, and they map to ideas you have already met. Append-style incremental processes a new partition each run (today’s events) and writes it, ideal for immutable, time-stamped data. Merge-style incremental processes changed records since a watermark (Chapter 7) and upserts them, ideal for mutable records like orders that update.
The state is the whole risk. Full refresh is simple and self-healing and does not scale; incremental is efficient and has to remember where it got to. The lab below crosses the two ways of writing that memory down with the two ways of writing the rows — one of the four cells loses data permanently and nothing anywhere reports it.
Core mental model
Incremental = "do only the new work". Append new partitions for immutable data; merge changed records for mutable data. Efficient, but it carries state you must get right.
Why it matters
Incremental processing is what keeps pipelines affordable and fast at scale. But it adds state and edge cases, so understanding when it is safe, and how to recover when it drifts, is essential to running it in production.
append-style incremental
Processing and adding a new partition each run; for immutable, time-stamped data.
merge-style incremental
Processing changed records since a watermark and upserting them; for mutable records.
processing state
The record of what has already been processed (a watermark or processed-partition list).
full refresh
Reprocessing the entire dataset; simple and self-healing but does not scale.
412 rows changed since the last run · 3 of them share the boundary instantStrictly greater loses them. Greater-or-equal keeps them, and duplicates them unless the write is keyed.3 lost · 0 duplicated
SELECT * FROM orders WHERE updated_at > '2026-03-14 09:00:00.000'
Comparison
Write
The task retried
3 rows silently lostThree rows were written at exactly the watermark instant. A strictly-greater comparison excludes them and the next run starts after them too, so they are never read by anything. Nothing fails, the row count is plausible, and the loss is permanent.
Why this is askedEvery one of the four cells is a real production design somebody shipped. The interviewer is not checking whether you know what a watermark is — they are checking whether you noticed that the comparison and the write mode have to be chosen together, because neither is safe on its own.
Incremental vs full reprocessing
Aspect
Incremental
Full refresh
Work per run
Only new/changed data
The entire dataset
Cost at scale
Stays low
Grows until infeasible
Complexity
Higher (tracks state)
Lower (stateless)
Self-healing
No, drift needs a backfill
Yes, recomputes everything
Default choice
Yes, for the bulk
Fallback / small datasets
Common mistake
Running a full refresh nightly on a large, ever-growing table. The job grows slower every day until it no longer finishes in its window.
Trusting incremental state without a way to fully reprocess. When the state drifts (a missed run, a bug), there is no clean path back to correct data.
Better habit
Default to incremental for large datasets; keep a full reprocess available.
Match append- vs merge-style to whether the data is immutable or mutable.
Treat incremental state as something that can drift and must be recoverable.
Production reality
dbt’s "incremental" models are exactly this: process new/changed rows and merge them, with a documented "full-refresh" escape hatch. The pattern, incremental by default, full reprocess on demand, is the industry norm.
Remember this
Incremental processing handles only new or changed data (append for immutable, merge for mutable), keeping pipelines fast at scale, at the cost of state you must be able to fully reprocess when it drifts.
Practice2 prompts
Choose append- or merge-style incremental for: clickstream events, customer records.
Explain why incremental needs a full-reprocess fallback.
04 · Backward
Backfills: Rewriting History Safely
A backfill is "re-run these past partitions". It is safe only because each partition is independent and idempotent, so reprocessing replaces rather than duplicates.
⏱ 6 min · Topic 4 of 8
A backfill re-runs the pipeline over past partitions. You backfill to populate history when a new pipeline goes live (compute the last two years), or to correct history after a bug or logic change (recompute March now that the rule is fixed). It is one of the most common real operations, and one of the most dangerous if the pipeline was not designed for it.
The diagram shows the shape: while normal daily runs continue on the latest partition, a backfill reprocesses a range of earlier partitions (here 06-01 to 06-03). Because each partition is independent and the load is idempotent (overwrite the partition), reprocessing a past day replaces it cleanly, no duplicates, no effect on other days. This is exactly why Chapters 9 and 11 spent so long on idempotency.
The cardinal rule is therefore: never backfill a non-idempotent pipeline. A backfill is just many re-runs, so if a single re-run duplicates data, a backfill multiplies the damage across every partition in the range. Backfill safety is not a property of the backfill command; it is a property of the pipeline being idempotent and partitioned.
Core mental model
A backfill is "re-run these past partitions". It is safe only because each partition is independent and idempotent, so reprocessing replaces rather than duplicates.
Why it matters
The ability to safely rewrite history is what lets a data team fix mistakes and improve logic without fear. A pipeline you cannot backfill is one whose past errors are permanent, a serious limitation that compounds over time.
backfill
Re-running a pipeline over historical partitions to populate or correct them.
partition-scoped reprocess
Reprocessing one partition at a time so each is replaced cleanly and independently.
backfill range
The set of past partitions a backfill covers (e.g. all of March).
historical correctness
Ensuring past partitions reflect the current, correct logic after a fix.
Fourteen months wrong · 426 logical dates to rebuildA backfill is a plan with a runtime, a share of the cluster and a story about tonight.5.3 h wall clock
Chunk size
Order
Parallel chunks
Write mode
The plan
426 chunks≈ 3 min each5.3 h wall clock≈ 48% of the warehousenewest first
Newest first means the dates people actually look at are correct within the first hour, and the tail can run for a day without anybody minding. This is almost always the right order and almost never the default.
Tonight’s run still fits — 48% leaves room for the nightly windowPartition overwrite makes each chunk idempotent, so an interrupted backfill can simply be resumed. Bounded concurrency is what keeps the scheduled work alive alongside it — and “bounded” is a number you chose, not a default you accepted.
Common mistake
Backfilling a pipeline whose writes are not idempotent. Every reprocessed partition duplicates its data, turning a correction into widespread corruption.
Backfilling a huge range all at once without throttling. You overwhelm compute and the source; backfills should run in controlled, partition-sized chunks.
Better habit
Only backfill pipelines that are idempotent and partitioned.
Reprocess partition by partition, replacing each cleanly.
Throttle large backfills into controlled chunks.
Backfill amplifies non-idempotency
If one re-run duplicates data, a backfill duplicates it across the whole range. The safety of a backfill lives entirely in the pipeline being idempotent, never in the backfill command itself.
Interview note
"I can backfill safely because each partition is reprocessed idempotently by overwrite" is the answer that ties this whole arc, partitions, idempotency, backfills, together. It is a strong senior signal.
Remember this
A backfill re-runs past partitions to populate or fix history; it is safe only when the pipeline is partitioned and idempotent, so reprocessing replaces data rather than duplicating it.
Practice2 prompts
Explain why backfilling a non-idempotent pipeline is dangerous.
Describe how you would backfill a year of data without overwhelming the system.
05 · The hard part
Late-Arriving Data & Replays
Late data belongs to the partition of when it happened, not when it arrived. Route it to that partition and reprocess (overwrite) it, a small, idempotent backfill, within a bounded lateness window.
⏱ 5 min · Topic 5 of 8
Data is not always punctual. An event that happened at 11:58 PM on Monday might not reach your pipeline until Tuesday, because of a mobile device that was offline, a delayed upstream system, or a network retry. This is late-arriving data, and it is one of the subtlest correctness problems in pipelines.
The danger is that a naive incremental pipeline already "closed" Monday’s partition and moved on, so Monday’s late event either lands in Tuesday (wrong day) or is dropped entirely. Either way, Monday’s numbers are quietly wrong. The fix builds directly on partitions and idempotency: route the late event to the partition it belongs to (Monday) and reprocess that partition, overwriting it with the corrected total.
Because reprocessing a partition is idempotent, handling late data is a targeted mini-backfill of the day it belongs to. What is left is one number: how long you leave the door open. Move it below and watch three things move with it — completeness, the number of partitions that can still change, and whether finance can ever close a month.
Core mental model
Late data belongs to the partition of when it happened, not when it arrived. Route it to that partition and reprocess (overwrite) it, a small, idempotent backfill, within a bounded lateness window.
Why it matters
Late data silently corrupts time-based metrics, and time-based metrics are most of analytics. Handling it correctly, by reprocessing the right partition, is what keeps "Monday’s revenue" actually equal to Monday’s revenue, even when some of it arrived on Tuesday.
event time vs processing time
When an event actually happened versus when the pipeline received it; late data is when they diverge.
allowed lateness
How long a pipeline keeps accepting and reprocessing late data for a partition.
partition reprocess
Overwriting the affected partition to incorporate late events, a targeted backfill.
finalisation
Declaring a partition final after the lateness window, so it stops being reprocessed.
412,000 events a day · most arrive within the hour, some take a fortnightAllowed lateness trades completeness against cost and against restating a published number.99.6% placed correctly
How long a partition stays open to late arrivals
what it costs you
at this setting
events in the wrong day, per day
1,648
partitions that may still be rewritten
2
times a published day is restated, per month
1
finance can close the month
yes
99.6% placed correctly, 1 restatement a monthThis is the shape of the honest answer: hold the partition open long enough to catch the bulk of the tail, publish, and restate on a known cadence that consumers have been told about. The number that matters is not the percentage — it is whether the people reading it know it can move.
The question underneathEvery setting here is defensible and none of them is complete-and-final-and-cheap. When an interviewer asks how you handle late data, the answer they are listening for is not a number of hours — it is that you know you are choosing between completeness, cost and finality, and that you would tell the consumers which one you chose.
Common mistake
Assigning late events to the day they arrived rather than the day they happened. Both days are wrong: the original understated, the arrival day overstated, and the totals never reconcile.
Treating partitions as permanently final the instant they are first processed. Legitimately late data is dropped, silently understating historical metrics.
Better habit
Assign events to partitions by event time, not arrival time.
Reprocess the affected partition when late data arrives, idempotently.
Define an allowed-lateness window, then finalise partitions.
Production reality
Streaming engines formalise this with watermarks and allowed-lateness (Chapter 14); batch pipelines do the same by reprocessing recent partitions on a rolling basis. Either way, the principle is identical: late data triggers a reprocess of its own partition.
Interview note
Explaining that late data is reprocessed into its event-time partition within an allowed-lateness window shows you understand the single hardest part of time-based pipelines, and ties it back to partitions and idempotency.
Remember this
Late-arriving data belongs to the partition of when it happened; handle it by reprocessing that partition idempotently within a bounded allowed-lateness window, so time-based metrics stay correct.
Practice2 prompts
Explain why a Monday event arriving Tuesday must be reprocessed into Monday.
Describe the trade-off an allowed-lateness window balances.
06 · Made real
A Bug Shipped Eleven Days Ago. Fix History.
A backfill is not one big job — it is N ordinary runs for N past dates, and the only reason that is safe is that each one rebuilds its own partition from raw.
⏱ 8 min · Topic 6 of 8
On the 3rd, a currency conversion started rounding the wrong way. Nobody noticed until the 14th, when finance asked why August was short.
Before writing a single command you have to answer three questions: which partitions are wrong, in what order they rebuild, and how fast you dare go. The grid below answers the first; the code answers the rest.
Core mental model
A backfill is not one big job — it is N ordinary runs for N past dates, and the only reason that is safe is that each one rebuilds its own partition from raw.
Why it matters
Backfills are where a calm engineer and a panicking one produce very different outcomes. Rebuilding too little leaves wrong numbers in production; rebuilding too much takes production down to fix them.
blast radius
The set of partitions a bug actually touched. Derived from the data rather than the deploy date, because a bug often needs a particular input to trigger.
lateness window
How many trailing partitions each run rebuilds. It is what lets a Monday event arriving on Tuesday reach Monday’s numbers.
restatement
Changing what a metric means and rebuilding history to match. A communication exercise with a backfill attached, not the other way round.
completion marker
A per-date record that the rebuild finished, so an interrupted backfill resumes rather than starting again.
A currency-conversion bug · found on the 14thBefore you can fix history you have to know how much of it is wrong.12 partitions
Which day did the bad code ship?How many partitions may rebuild at once?
August · silver.orders, one box per date partition
0102030405060708091011121314
Red partitions were built by the broken code. Everything before the 3th is correct and must not be touched — rebuilding a good partition is how a backfill creates new bugs.
What has to be rebuilt, and in what order
marlow-bronzeRAWUntouched. Never rebuilt.→marlow-silverREBUILDWhere the bug lives.→marlow-goldREBUILDDerived from silver.→finance reportRE-READRestated once gold lands.
12 silver partitions12 gold partitions3 waves~18 min
12 partitions, 4 at a time, about 18 minutesBronze is never rebuilt: it is what the rebuild reads from. Silver is rebuilt per date, then gold, then the report is restated. Consumers keep reading the old numbers until each partition swaps.
Finding the blast radius before you fix anythingworked example
SQL
-- when did the numbers start disagreeing with the source of truth?SELECTdt,SUM(total_gbp)ASwarehouse_total,SUM(raw_total*fx_rate)ASrecomputed_total,ABS(SUM(total_gbp)-SUM(raw_total*fx_rate))ASdriftFROMsilver.orderssJOINbronze.ordersbUSING(order_id,dt)JOINsilver.fx_ratesfONf.ccy=b.currencyANDf.dt=b.dtWHEREdt>=DATE'2026-07-25'-- look back well before the suspected dateGROUPBYdtHAVINGdrift>0.01ORDERBYdt;-- the first row is your true start date
Never take the deploy date on trust. Ask the data when the numbers changed shape — the answer is sometimes earlier than the release, because the bug needed a particular input to trigger.
The backfill itself — bounded, ordered, resumableworked example
SQL
#Airflow:11dates,fouratatime,intoapoolthatcapssourceconnectionsairflowdagsbackfillmarlow_orders_daily--start-date 2026-08-03 --end-date 2026-08-13 --max-active-runs 4 --reset-dagruns#dbt:thesamerange,and--full-refresh because the incremental#predicatewouldotherwiseskipdatesthatalreadyhaverowsdbtrun--select silver.orders+ --full-refresh --vars '{"start_date": "2026-08-03", "end_date": "2026-08-13"}'#PlainPython,whentheorchestratorisnotinvolved:onedateatatime,#andamarkersoaninterruptedbackfillresumesinsteadofrestartingfordtindate_range("2026-08-03","2026-08-13"):ifbackfill_log.done(dt):continuerebuild_partition(dt)#overwrite,neverappendbackfill_log.mark_done(dt)
Concurrency is the whole safety story. It is a limit on the source and the warehouse, not a speed dial, and a pool makes it a limit the platform enforces rather than one you remember.
Incremental with a lateness window, so yesterday can still changeworked example
SQL
-- rebuild the last 3 days every run, not just yesterday:-- a Monday event arriving on Tuesday still lands in Monday's partition{{config(materialized='incremental',unique_key=['dt','order_id'],partition_by={'field':'dt','data_type':'date'},incremental_strategy='insert_overwrite')}}SELECTorder_id,customer_id,total_gbp,dtFROM{{ref('bronze_orders')}}{%ifis_incremental()%}WHEREdt>=DATE_SUB(CURRENT_DATE(),INTERVAL3DAY){%endif%}
A strictly forward-only incremental never revisits a closed day, so a late event is lost. Reprocessing a trailing window costs a little every night and removes an entire class of silent error.
Spark: rebuild one date without touching its neighboursworked example
The two settings that make a per-date rebuild safe. Without dynamic mode, a partitioned overwrite deletes every partition in the table — the classic backfill catastrophe.
The three ways history gets rewritten, and how they differ
Catchup
Backfill
Restatement
Why
The scheduler was down
The logic was wrong
The business definition changed
What changes
Nothing — runs that never happened
The code, then the outputs
The meaning of a metric
Range
The missed dates
From the bug to now
Often all of history
Who is told
Usually nobody
The consumers of that table
Everyone, in writing, before it lands
Risk
A stampede on the source
Rebuilding good partitions too
Two versions of a number in circulation
Backfill safety checklist — every one of these has caused an outage
Check
What goes wrong without it
Is every write partition-scoped?
One run overwrites the whole table instead of its date
Is dynamic partition overwrite on?
Spark deletes every partition not present in this batch
Is concurrency bounded?
Eleven parallel rebuilds saturate the source and stall tonight’s run
Does it read from raw, not the broken layer?
You rebuild the bad numbers faithfully
Is there a per-date completion marker?
An interrupted backfill restarts from the beginning
Do downstream marts rebuild too?
Silver is right, gold still shows the old totals
Have consumers been told?
Someone screenshots a number mid-backfill and quotes it in a meeting
Is there a rollback?
The fix is wrong and there is now no correct version of the data
Choosing the reprocessing unit
Partition by
Rebuild costs
Suits
Watch out for
Day
One day of compute
Almost everything
Low-volume tables get thousands of tiny files
Hour
One hour
High-volume events, tight SLAs
24× the partition count and the metadata that comes with it
Month
A whole month
Small, slow-changing reference data
Fixing one day means rebuilding thirty
Entity (region, tenant)
One tenant
Multi-tenant systems where blame is per tenant
Skew — one tenant is 80% of the data
Common mistake
Backfilling from the broken layer instead of from raw. The fixed code faithfully reproduces the wrong numbers, and everyone believes the problem is solved.
Trusting the deploy date as the start of the blast radius. The bug needed a particular input, so it started earlier — and those partitions stay wrong after the backfill "completes".
Running the backfill unbounded because it is urgent. The source and the warehouse saturate, tonight’s scheduled run misses its SLA, and the incident doubles in size.
Rebuilding silver and forgetting the marts built on it. The clean layer is correct and every dashboard still shows the old totals, which is indistinguishable from the backfill having failed.
Better habit
Derive the blast radius from the data, then widen it by a day for safety.
Read from raw, write partition-scoped, and mark each date done as you go.
Bound concurrency with a pool, so the limit survives whoever runs it next.
Rebuild downstream in dependency order, and tell consumers before they notice.
The backfill that takes production down
The fastest backfill is the one that saturates the source. Eleven concurrent rebuilds means eleven times the reads and eleven times the warehouse slots, so the nightly run queues behind your fix — and now you have two incidents.
The follow-up you will actually get
"A bug has been in production for two weeks. Walk me through fixing history." Lead with scope — how you find the true first bad partition — then per-date rebuilds from raw, bounded concurrency, downstream rebuild order, and who you tell. Candidates who open with a command have skipped the entire job.
Remember this
A backfill is N ordinary runs over past dates: find the true blast radius from the data, rebuild each partition from raw with a bounded concurrency, then rebuild everything downstream — and say so out loud before someone quotes a half-fixed number.
Practice2 prompts
Write the query that would tell you when a metric you own started drifting, without looking at deploy history.
For a table you own, name the concurrency you could safely backfill at, and what that number is limited by.
07 · Practice
Practice Lab
If a single day cannot be rewritten on its own, no backfill strategy will save you. Partition first.
⏱ 3 min · Topic 7 of 8
Five scenarios about the partition as the unit of reprocessing — forward as an incremental load, backward as a backfill that must not break tonight.
Build them on the pipeline canvas with the chapter closed. Each is graded against the scenario’s own requirement rules rather than against a model answer, so there is more than one design that passes — and a design that does not pass is told exactly which requirement it missed.
Core mental model
If a single day cannot be rewritten on its own, no backfill strategy will save you. Partition first.
Why it matters
Backfilling is asked about constantly because everybody has done one badly. These scenarios put you in front of the two classic failures: the backfill that double-counts, and the one that silently reverts a hand-repair.
Common mistake
Backfilling onto an appending load, which adds a second copy of every row it touches. The review will find it, but only after you have submitted a design you believed in — which is the point. That is the memory that survives interview pressure.
Revealing the reference design before your own review comes back. You see what correct looks like without finding out what your version got wrong, and your version is the one you will draw again under pressure.
Better habit
Backfill only closed partitions, and never let a backfill and the nightly run write the same slice at once.
Run the review, fix what it finds, and run it again. The second score is the one that means something.
Narrate the finished design out loud in ninety seconds. If you cannot, the design has a hole you have not found yet.
Incremental and backfill are the same mechanism pointed in opposite directions. Building the forward case first makes the backward one obvious.
These are the round, not a warm-up
Five graded design scenarios, each with staged requirement checks and interview probes of its own. Working them out loud, against a clock, is the closest rehearsal to the real thing this module offers.
Remember this
A chapter read is a chapter you can recognise; a scenario built and reviewed is one you can use. Close this and go build.
Practice2 prompts
Before opening any scenario, write down the freshness requirement and who consumes the output.
After each review, write one sentence naming the requirement you missed and why you missed it.
08 · Next Chapter
Next Chapter
You have now completed the building and orchestration arc: extract, transform, load, orchestrate, and reprocess, all built on idempotency and partitions. Next the course turns to a new world: unbounded, real-time data.
⏱ 3 min · Topic 8 of 8
Next chapter
Streaming Architecture Fundamentals
You have now completed the building and orchestration arc: extract, transform, load, orchestrate, and reprocess, all built on idempotency and partitions. Next the course turns to a new world: unbounded, real-time data.
Chapter 13 begins the Streaming & Real-Time level with streaming architecture fundamentals: producers, brokers, consumers, topics, partitions, and offsets, the Kafka / Kinesis / Pub-Sub model that powers real-time pipelines.