Structured Data Practice Exercises
In the capstone you built a complete budget tracker with models, CRUD, transactions, and a Neon connection. Now you put those skills under pressure, independently and with a timer running.
Getting stuck is not failure. Quitting is. These exercises are meant to be challenging. If everything felt easy, you would not be learning anything new. The moments where you stare at an error message and think "I have no idea what went wrong" are the moments where real understanding forms.
If you are stuck for more than 10 minutes on one part, move on and come back. Sometimes the later exercises give you a new perspective on the earlier ones.
You might be thinking: "I don't know where to start." That is fine. The hints are there. Use them.
One rule above all others:
- Claim nothing. Prove everything.
How to Use
- Read the exercise brief.
- Implement or debug.
- Collect evidence artifacts.
- Write a short postmortem.
Evidence Format (Use Across All Exercises)
For each exercise, submit:
DECISIONS.md: what you changed and whyEVIDENCE.md: commands run, outputs, and pass/fail summary- one explicit "known risk" note after completion
This keeps your practice aligned with capstone release discipline.
Timebox suggestion:
- Core 1: 25 minutes
- Core 2: 30 minutes
- Core 3: 30 minutes
- Core 4: 35 minutes
If you run out of time, finish evidence for completed work instead of starting a new unfinished exercise. Incomplete evidence for a finished exercise teaches you nothing. Complete evidence for half the exercises teaches you the discipline that matters in production.
Core Track (Mandatory)
Complete all four exercises below.
Glossary for Core Track
Term Meaning Model integrity Your SQLAlchemy models enforce correct data through types, constraints, and foreign keys, not through hope CRUD Create, Read, Update, Delete: the four basic operations every database application needs Rollback proof Evidence that a failed operation left zero partial writes in the database Session boundary The explicit with Session(engine) as session:block where all database mutations happenN+1 query A performance bug where your code runs one query per row instead of one query for all rows
Core 1 - Model Integrity Build
Goal: Build User, Category, Expense-style models for a new domain.
Pick a domain you find interesting: a recipe tracker, a reading list, a workout log, a pet adoption registry. The specific domain does not matter. What matters is that you define real relationships between real entities with real constraints.
Deliverables:
- model file with constraints + foreign keys
MODEL-VERIFICATION.mdwith 3 query checks
Minimum evidence:
- schema output
- one invalid insert failure proof
- one explanation of why chosen types prevent ambiguity
Quality gate:
- reject any solution that stores money in float
- reject any solution that represents relationships only through free-text identifiers
Hint: Where to start
Start by listing the entities in your chosen domain. What are the "things"? What connects them? For a recipe tracker, the things might be Recipe, Ingredient, and RecipeIngredient (the join table). Once you have the entities on paper, turn them into SQLAlchemy models the same way you did in Lesson 3. Constraints and foreign keys come from asking: "What should the database refuse to store?"
Core 2 - CRUD Reliability Build
Goal: Implement create/read/update/delete with session + rollback discipline.
This is the exercise where muscle memory forms. You have seen CRUD in the lessons. Now build it from scratch for your own domain, without copying and pasting. When the rollback test passes, you will feel it click.
Deliverables:
- CRUD module
CRUD-EVIDENCE.mdwith before/after snapshots
Minimum evidence:
- one successful write
- one failed write with rollback proof
- one query proving no accidental duplicate rows
Quality gate:
- reject any solution that catches exceptions without rollback
- reject any solution that mutates state outside explicit session boundaries
Hint: Where to start
Copy the CRUD pattern from Lesson 4 and adapt it. Do not write from scratch. Adapting a working pattern to your domain is faster and teaches you to recognize which parts are universal (session management, commit/rollback) and which parts are domain-specific (the fields you create and query). Change the model names and fields, then run it.
Core 3 - Relationship Query Debug
Goal: Fix a broken relationship setup and return correct joined results.
This exercise is different from the others. You are not building from scratch. You are handed broken code and your job is to find what is wrong, fix it, and prove the fix works. Debugging relationship definitions is one of the most common real-world SQLAlchemy tasks.
Deliverables:
- corrected relationship definitions
RELATIONSHIP-TRACE.md
Minimum evidence:
- bidirectional navigation works
- one
join()query returns expected rows - one N+1 risk identified and corrected
Quality gate:
- reject solutions with mismatched
back_populates - reject solutions that only test one relationship direction
Hint: Where to start
The bug is in the relationship definitions. Check back_populates first. The most common mistake is that back_populates on one side points to a name that does not exist on the other side, or the names are swapped. Print both sides of the relationship (parent.children and child.parent) to confirm navigation works in both directions before moving to join queries.
Core 4 - Transaction + Neon Ops Drill
Goal: Prove atomic multi-step writes and cloud connection reliability.
This is the closest exercise to production work. You are combining local transaction safety with a real cloud database connection. When your forced-failure test leaves zero partial writes AND your Neon health check passes, you have completed the full Chapter 9 skill chain.
Deliverables:
transfer_*transaction function- Neon connection config + health check script
OPS-EVIDENCE.md
Minimum evidence:
- forced failure leaves zero partial writes
- Neon
SELECT 1passes - pool settings documented and justified
Quality gate:
- reject releases without rollback drill output
- reject configs that hardcode credentials
Hint: Where to start
Start with the SELECT 1 health check. If that works, everything else is CRUD + rollback on top of a connection you already trust. Write the health check script first, confirm it connects to Neon, then build the transfer function locally with SQLite, then switch to the Neon connection string. Small steps, each verified before the next.
Challenge Track (Optional)
These exercises go beyond the chapter baseline. They simulate real production scenarios where the answer is not obvious and the stakes are higher.
Choose one or more.
Glossary for Challenge Track
Term Meaning Verification gate A check that must pass before code ships: if the numbers disagree, the release is blocked CSV migration Moving data from flat CSV files into a normalized relational schema without losing rows Incident recovery Diagnosing a broken production state, fixing it safely, and proving nothing else broke Row-count reconciliation Confirming that every row in the source data appears in the destination after migration Regression proof Evidence that your fix did not break something that was previously working
Challenge A - High-Stakes Verification Gate
Build SQL summary + independent raw-ledger verification.
Evidence:
mismatch-policy-result.json- clear release block decision when mismatch exceeds tolerance
- mismatch triage notes
Use this challenge if your target role includes finance, compliance, or audit-sensitive workflows.
Challenge B - Legacy CSV Migration
Normalize a messy multi-file dataset into relational schema.
Evidence:
- row-count reconciliation
- key-field parity checks
- explicit list of non-lossy transformations
Challenge C - Recovery Under Incident
Given a broken budget app state, prioritize fixes and recover safely.
Evidence:
- prioritized fix log
- regression proof after recovery
- short incident postmortem with prevention actions
Use this challenge if your target role includes operations ownership or on-call responsibilities.
Outcome Mapping
| Outcome | Core track coverage | Challenge extension |
|---|---|---|
| Model correctness | Core 1 | Challenge B |
| Safe CRUD | Core 2 | Challenge C |
| Relationship correctness | Core 3 | Challenge B |
| Transaction safety | Core 4 | Challenge C |
| Neon reliability | Core 4 | Challenge C |
| Hybrid judgment | Core 4 | Challenge A |
If you complete all Core exercises with clear evidence, you meet Chapter 9 baseline mastery. Challenge track pushes you toward production-level judgment.
Suggested Scoring for Self-Assessment
Use a 0-2 scale for each criterion per exercise:
Model correctnessWrite safetyQuery correctnessFailure-path evidenceOperational clarity
Interpretation:
8-10: ready for capstone-level work6-7: repeat one core exercise with stricter evidence<6: revisit lesson material before continuing
A score below 6 is not a verdict on you. It means the material needs another pass. Go back to the lesson that covers your weakest criterion, re-read the key section, then try the exercise again with that specific gap in mind.
Try With AI
Setup: Open Claude Code, Cursor, or Windsurf in a project directory with your exercise files.
Prompt 1: Evidence Review
Here is my EVIDENCE.md for the CRUD exercise:
[paste your EVIDENCE.md]
Review this evidence file. For each claim I make:
1. Is the evidence sufficient to prove the claim?
2. What additional evidence would make the proof stronger?
3. Are there any claims I made without supporting output?
Be strict. In production, reviewers will be stricter than you.
What you're learning: You are building the skill of self-auditing. Production teams reject pull requests with claims like "this works" and no proof. By having AI critique your evidence, you learn what "sufficient proof" actually looks like, and you carry that standard into every future exercise.
Prompt 2: Failure Scenario Generation
I built a CRUD module for [your domain] with these models:
[paste your model definitions]
Generate 5 failure scenarios I should test:
- 2 involving constraint violations
- 2 involving transaction rollback
- 1 involving a relationship navigation bug
For each scenario, tell me what to try AND what the correct
behavior should be. I want to test these myself, not have
you fix them.
What you're learning: You are practicing defensive thinking. Production bugs do not come from the happy path. They come from the cases you did not consider. By asking AI to generate failure scenarios, you learn to think about what could go wrong before it goes wrong, which is the core skill behind "claim nothing, prove everything."