Module 4 of 9 · Lesson 11 of 26
Backfill existing data in bounded batches
Work through backfill existing data in bounded batches using a runnable reference, a focused regression check and a local extension.
Read in any order. All lessons stay open, including after an unanswered or incorrect check.
Batching limits lock duration and transaction size. It does not make every large migration risk-free: indexing, application compatibility and concurrent writers still need review. First deploy code that tolerates the expanded shape, run and observe the backfill, verify no missing values remain, and then add the final constraint in a later migration. The bundled 0002 migration is a small-data example in one transaction. The separate helper demonstrates independent batch commits; using it inside an existing migration transaction would be a different behavior. Count processed batches or rows without logging learner records or credentials. Do not overwrite non-null values merely to make every row look identical.
The lesson11 fixture temporarily makes condition nullable only in its disposable database. It creates three missing values, uses a batch size of two, expects two committed batches, reruns expecting zero, and restores NOT NULL. This intentionally simulates an intermediate schema rather than weakening the application's final schema.
def backfill_condition(engine, batch_size=100):
if batch_size < 1:
raise ValueError("Batch size must be positive")
batches = 0
while True:
with engine.begin() as connection:
identifiers = (
connection.execute(
select(Equipment.id)
.where(Equipment.condition.is_(None))
.order_by(Equipment.id)
.limit(batch_size)
)
.scalars()
.all()
)
if not identifiers:
break
connection.execute(
update(Equipment)
.where(Equipment.id.in_(identifiers), Equipment.condition.is_(None))
.values(condition="ready")
)
batches += 1 # each batch commits; rerunning ignores already-filled rows
return batches
python run_checks.py -k lesson11
Expected result The selected lesson test passes against a new temporary PostgreSQL database; the container is removed afterward.
Keep for reference
Equipment Rental lab and lesson checks
ZIP containing Python source, real Alembic migrations, 26 lesson checks, a dependency lock and text instructions. Extract it before following the local exercise.
Practise locally
Add a valid custom condition to one item and several missing values to your own expanded test schema. Stop after one batch, rerun the job, and verify the custom value survives while all missing values become ready. Record batch counts and the final null count. Write the verification query you would require before a later NOT NULL migration.
The lesson check verifies the reference behavior. Add your own assertions for your change. Local practice is not uploaded or scored by this learning release.
Pause and reflect
What failure does this lesson prevent, and which assertion in lesson11 would expose it?
Use a concrete input, expected result and limitation from your local work. Saving a reflection does not certify the project.
Optional knowledge check
What makes this backfill safe to resume?
It rewrites every row on every run, including user-supplied values.
Try another answer. That could destroy valid existing values and repeatedly expand the work.
Run every batch inside one surrounding transaction and call it independently committed.
Try another answer. A surrounding transaction changes the durability and lock-duration behavior.
It changes only rows still missing the value and commits bounded batches.
Correct. Completed rows are skipped after interruption, and each batch has a clear transaction boundary.
This practice does not assess your project or award a certificate.
Your reading progress
Progress is saved in this browser when storage is available.