Why this matters
- Over-normalised schemas force five-table JOINs on every product page; under-normalised schemas let one address change corrupt hundreds of shipped labels.
- Interviewers ask for 1NF–3NF definitions and when to break them — both sides matter in production.
- VaultCommerce's reporting team and checkout team often disagree on schema shape; normalization vocabulary settles the debate.
- Understanding anomalies (update, insert, delete) explains why duplicate
customer_emailon every order row is dangerous.
First normal form (1NF)
Each column holds atomic values; no repeating groups. Bad design stores multiple tags in one column:
-- Violates 1NF
CREATE TABLE products_bad (
id BIGSERIAL PRIMARY KEY,
name TEXT,
tags TEXT -- 'sale,wireless,bestseller'
);
VaultCommerce uses a product_tags junction table — one row per tag assignment — satisfying 1NF.
Second normal form (2NF)
2NF requires 1NF plus every non-key column depends on the entire primary key. On a composite key (order_id, product_id), product_name must not live in order_items if it depends only on product_id:
-- 2NF: product name lives in products, not order_items
CREATE TABLE order_items (
order_id BIGINT,
product_id BIGINT,
quantity INTEGER,
unit_price_cents INTEGER, -- depends on (order_id, product_id) snapshot
PRIMARY KEY (order_id, product_id)
);
unit_price_cents depends on the line — it is a valid snapshot. product_name belongs in products.
Third normal form (3NF)
3NF requires 2NF plus no transitive dependencies — non-key columns must depend only on the primary key, not on other non-key columns.
-- Violates 3NF: category_name depends on category_id, not product id
CREATE TABLE products_bad (
id BIGSERIAL PRIMARY KEY,
name TEXT,
category_id BIGINT,
category_name TEXT -- transitive dependency
);
-- 3NF: category name in categories table
CREATE TABLE categories (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL
);
Without normalization, updating a category name touches thousands of product rows (update anomaly), and deleting the last product in a category can orphan the category label (delete anomaly).
When to denormalize
Read-heavy paths that cannot tolerate multi-table JOINs justify controlled duplication:
-- Denormalized summary table refreshed nightly
CREATE TABLE product_sales_summary (
product_id BIGINT PRIMARY KEY,
units_sold_30d INTEGER NOT NULL,
revenue_cents_30d BIGINT NOT NULL,
refreshed_at TIMESTAMPTZ NOT NULL
);
The ETL job aggregates from normalized order_items; the product listing API reads one row per SKU. Staleness of up to 24 hours is acceptable for "bestseller" badges.
VaultCommerce denormalization triggers
- Read latency — Hot catalog endpoints cannot JOIN five tables at 10k RPS.
- Reporting snapshots — Finance needs frozen monthly totals, not live recalculation.
- Search indexes — Elasticsearch documents embed category names for facet filters.
Balancing the trade-off
| Aspect | Normalized (3NF) | Denormalized |
|---|---|---|
| Writes | Single update point | Multiple copies to sync |
| Reads | JOINs required | Single-table fetch |
| Integrity | Constraints enforce truth | Application or ETL must reconcile |
| VaultCommerce use | Orders, payments | Bestseller badges, search docs |
Writes
Normalized (3NF)Single update pointDenormalizedMultiple copies to syncReads
Normalized (3NF)JOINs requiredDenormalizedSingle-table fetchIntegrity
Normalized (3NF)Constraints enforce truthDenormalizedApplication or ETL must reconcileVaultCommerce use
Normalized (3NF)Orders, paymentsDenormalizedBestseller badges, search docs
Start normalized; denormalize only when profiling proves JOIN cost exceeds maintenance burden.
Quick recall
Everything you need if you only revisit this box.
- 1NF eliminates repeating groups; 2NF removes partial key dependencies; 3NF removes transitive dependencies.
- Normalization prevents update, insert, and delete anomalies.
- VaultCommerce keeps orders normalized; summary and search tables denormalize for read speed.
- Denormalize only with a refresh strategy and documented staleness tolerance.
- Default to 3NF for transactional data; break rules for measured read bottlenecks.
Test yourself
Answer these before moving on — recall is what makes it stick.