One fact, stored once
The normal forms arrive wrapped in intimidating vocabulary, but the working version fits in one sentence. Store each fact exactly once, and point at it from everywhere else.
A customer's name lives in one row of your customers table, and every order carries the customer's identifier, not their name.
The forms are a checklist for finding duplication you did not notice. The first one says no repeating groups, so no columns called phone1, phone2 and phone3; phone numbers get a table of their own.
The next two say every column should be a fact about that row's key and nothing else. If your orders table carries the customer's city, that is a fact about the customer, not about the order, and you have copied it onto every order they ever place. Third normal form is where most schemas comfortably settle, and chasing forms past it is rarely worth the meetings.
Why duplication is a correctness problem
This matters for a reason that is not storage, because the answer is not storage. Duplication is a correctness problem.
Every duplicated fact can be updated in one place and missed in another, and now your database holds two answers to one question with no record of which is right. The textbook names for the failure modes all describe the same disease: facts disagreeing with themselves.
A clean schema makes your writes trivially correct. Renaming a customer is one update to one row, and every join reflects it immediately.
You pay on your reads. Showing an order with the customer name, the product names and the shipping city is now a four-table join. For most applications at most sizes that price rounds to zero, because a relational database joins millions of rows a second with a planner tuned by decades of exactly this.
So normalise first. The next lesson is about what happens when most sizes stops describing you.
Worked example
Dana inherits a freight platform where the schema was built by copying spreadsheets: shipments, invoices, and quotes tables each carry their own customer_name and customer_address columns. A customer called Brenner Logistics rebrands to BLX Freight and asks for the name change. The update touches three tables, and the script misses quotes because a colleague filtered on the old name with a typo. For five months, new invoices say BLX Freight while renewal quotes say Brenner Logistics, and the customer's procurement team rejects a 60,000 dollar quote as "not our vendor," which is how the bug is finally found. Dana's fix is the boring one: a customers table holding name and address once, foreign keys everywhere else, and a migration that reconciles 14 conflicting address spellings along the way. The next rename, months later, is one UPDATE statement.