ACE AI Startup Bootcamp · Day 3 Companion Guide
On Day 1 you drew the screens. On Day 2 you drew the flow. Today you build the skeleton of the data that sits underneath both. Read this for 15 minutes before the session, then keep it open during the lab.
Without a reason to care, normalization is just three things to memorise.
Think of building a house.
Coding starts on Day 6. If the wiring diagram is wrong by then, every screen and API you have already built has to be undone. In a 10-day bootcamp that is fatal. Hence today.
Start from the definition and you will bounce off it. So let's start from the pain.
Say you are building an online course platform. At first, one sheet does everything.
| # | Student | Student phone | Courses | Instructor | Instructor phone | Fee (₦) |
|---|---|---|---|---|---|---|
| 1 | Chidi Okeke | 0801-111-1111 | AI Product Planning, Data Analytics | Ngozi Eze | 0809-999-9999 | 120,000 |
| 2 | Amina Bello | 0802-222-2222 | AI Product Planning | Ngozi Eze | 0809-999-9999 | 60,000 |
| 3 | Chidi Okeke | 0801-111-1112 | Prompt Engineering Lab | Kwame Mensah | 0808-888-8888 | 90,000 |
This sheet has already booked three accidents. Engineers call them anomalies.
You launch a new course, "AI Ethics", with zero students so far. → There is no way to record it. No student, no row.
Chidi changes his number. → You must edit every row where Chidi appears. Someone edited row 3 only, so rows 1 and 3 now disagree. Which one is true?
Amina refunds, so you delete row 2. → If that was the last row for "AI Product Planning", the course itself vanishes too.
Splitting one sheet into purpose-built tables so those three accidents cannot happen. That's it. 1NF/2NF/3NF is just a three-step checklist for where to cut.
The question to ask: is there any cell where you stuffed several things in, separated by commas?
In Table A, Courses: "AI Product Planning, Data Analytics" is exactly that. Now try to answer "how
many students are in AI Product Planning?" — you have to chop strings apart. That way lies pain.
The fix: add rows instead. One value per cell — Chidi becomes two rows.
A,B,C into a single cell for things like tags, interest categories, or
attachments. It reads naturally in a planning doc and it is the most common 1NF violation there is. If a
field smells like it could hold more than one thing → it becomes its own table.
After 1NF, each row is identified by a two-part name tag: (student + course). Chidi–AI Planning, Chidi–Data Analytics, and so on.
The question to ask: to fill in this cell, do I need both halves of the name tag, or just one?
| Column | What do you need to know it? | Verdict |
|---|---|---|
| Enrolment date | student and course — both | stays in this table |
| Student phone | student only (course is irrelevant) | evicted → Student table |
| Course title / fee | course only (student is irrelevant) | evicted → Course table |
So 2NF = "if half the name tag is enough to determine a column, that column moves out with that half." This is the step that kills the update anomaly — fix Chidi's number once in the Student table and you're done.
Now look at the Course table: course_id, title, instructor_name, instructor_phone.
The question to ask: is this column determined by the name tag (course_id), or by another column sitting next to it?
The fix: create an Instructor table and leave only instructor_id in Course.
Is normalization always right? No. Normalization buys write consistency and sells read performance. Split into five tables and a single screen now costs five JOINs.
amount_paid must not point at the
product's current price — if the price changes later, every past receipt is silently rewritten. Facts
that belong to a moment in time get copied, not referenced.The symbols aren't the hard part. The hard part is that nobody tells you how to decide which symbol to use.
ERD (Entity Relationship Diagram), in plain words: "a picture of what exists and what connects to what."
| Type | Reads as | Example | How it's actually built |
|---|---|---|---|
| 1:1 | one to one | User ↔ User profile detail | Usually just merge into one table. If you split it, write down why. |
| 1:N | one to many (most common) | 1 instructor → many courses | Put the "1" side's ID on the "N" side (instructor_id lives in Course). ← beginners get this backwards constantly |
| N:M | many to many | Student ↔ Course | Cannot exist in a database. See below |
↑ One sheet became four tables. Note how the Student–Course N:M was split into two 1:N relationships via ENROLMENT.
| Symbol | Means | Mermaid |
|---|---|---|
| || | exactly one (mandatory) | ||--|| |
| o| / |o | zero or one (optional) | |o--|| |
| o{ (crow's foot) | zero or more | ||--o{ |
| |{ | one or more (at least one required) | ||--|{ |
The little circle means "it's allowed to be empty." If an instructor can exist with no courses yet, use
||--o{. If they must have at least one, use ||--|{. That distinction becomes your "is
this field required?" rule later.
erDiagram
STUDENT ||--o{ ENROLMENT : "enrols in"
COURSE ||--o{ ENROLMENT : "contains"
STUDENT {
int student_id PK
string name
}
Keep entity names in UPPERCASE English — some tools break on other scripts. PK is the table's own ID; FK is an ID pointing at another table.
ENROLMENT.student_id points at
STUDENT.So here is today's decision for your team: "when a user deletes their account, do we delete their records too, or keep them?" — this is not a technical question. Refunds, settlements and reporting all hang on it. Which is exactly why a non-engineer has to make the call.
Databases offer three options: CASCADE (delete children too) /
RESTRICT (refuse deletion while children exist) / SET NULL (cut the link, keep the
record). In practice most live services never hard-delete — they add a deleted_at column
(soft delete). But note the tension: data-protection law may require actual erasure, so decide explicitly
what you anonymise vs. what you retain and log it today. Day 8 (accounts) and Day 9 (payments) will hand
you the bill for this decision.
Task 03 feels impossible because it asks you to imagine something breaking that doesn't exist yet.
Schema = the blueprint of your tables: which columns exist and what type they are. Think of it as the constitution of your data.
Impact analysis is not forecasting. It is map-reading. You start at one column and follow the lines, asking "does this pass through here?"
↑ Change one column and at least five places wobble. Three of them are not code — they are documents and people.
This diagram is also the answer to "why does Task 02 (terminology standardisation) matter?" Agree on the words up front and this domino never starts. Standardising vocabulary isn't admin busywork — it is the cheapest insurance you will ever buy.
| Grade | Change | Why | What to do |
|---|---|---|---|
| Safe | Add an optional column | Existing code doesn't know it exists, so it ignores it | Just do it |
| Caution | Rename a column; add a required column | Everything reading it breaks; and there is no value to backfill | Write the impact list first |
| Dangerous | Drop a column, change a type, split a table | Irreversible. Data actually disappears | Backup + full team agreement + decision log |
Your Task 03 deliverable can be exactly this table. One row per change.
| Change | Grade | APIs affected | Screens affected | Existing data | Decision / alternative |
|---|---|---|---|---|---|
| USER.phone → mobile | Caution | GET /users, POST /signup | My Page, Signup form | Copy values, keep old column 2 weeks | Chose keep both for a while over an immediate drop |
| Add pay_status to ENROLMENT | Safe | GET /enrolments | My Courses | Default 'pending' | Proceed as-is |
The professional answer is an expand–contract migration: ⓐ add the new column → ⓑ dual-write to both → ⓒ backfill existing rows → ⓓ switch reads to the new column → ⓔ drop the old one much later. You never rename in one shot. "Keep both for a while" in the table above is the compressed version. Seen this way, impact analysis is a dependency-graph problem, not an ERD problem — the database is the root, not a leaf, and APIs, screens, docs, analytics queries and even your team's vocabulary all sit on top of it.
Today the AI is not your database designer. It is your hostile reviewer. Copy its answer down and you will never learn why it's right.
"Design the database for our service."
No context, so you get generic output — and then you present an ERD you cannot explain.
"Here are our meeting notes. Extract candidate entities and, for each one, justify why it deserves its own table. Where it's ambiguous, say it's ambiguous."
All ticked? You're ready for Day 4 (API design). Anything unticked is your question for the AI or the TA.
| Term | In plain words | Why you should care |
|---|---|---|
| Entity | one table / a noun you count separately | Get it wrong and you end up with far too many or too few tables |
| Attribute | a column | "Entity or attribute?" is today's core judgement call |
| Schema | the blueprint; the constitution of your data | Change it and everything on top shakes |
| Cardinality | how many to how many | Get 1:N backwards and the screen cannot be built |
| Primary key (PK) | that row's ID number | The basis for deciding what counts as a duplicate |
| Foreign key (FK) | a finger pointing at another table | This is what actually creates a relationship |
| Referential integrity | something must exist where the finger points | Prevents ghost records |
| Normalization | splitting so each fact is written once | Stops your data from contradicting itself |
| Anomaly | the three accidents caused by not splitting | The entire reason normalization exists |
| Junction table | the middle table an N:M gives birth to | Miss it and the design collapses |
| Migration | moving already-stored data to a new design | The real cost of any change |
| Mermaid | a tool where you write text and get a diagram | Lets you version-control an ERD like code |
ACE AI Startup Bootcamp · Day 3 companion guide — this does not replace the official curriculum (Day 3 AI Classroom). Use it as pre-reading and as a lab reference.
When stuck, in this order: ① the matching section above → ② Codex AI with one of the five prompts → ③ your TA or instructor. Never sit on the same blocker for more than 20 minutes.