Chapter 08 · Normalization: First, Second, and Third Normal Forms

When a Normalized Design Is Still a Bad Design

Learn why a schema can satisfy 3NF and still be difficult, misleading, inefficient, insecure, or semantically wrong—and how to review design beyond formal normal forms.

Beginner65–90 minutesDesign critique + tradeoffsLast reviewed: August 2026

Learning outcomes

A schema can satisfy 3NF and still be a bad design. Normal forms address specific dependency-based redundancy problems; they do not automatically solve poor naming, wrong entity boundaries, missing temporal semantics, weak integrity, unusable APIs, performance bottlenecks, privacy risks, or misunderstood business rules.

01

Separate formal normalization quality from overall data-model quality.

02

Recognize semantically wrong but normalized schemas.

03

Recognize over-fragmentation and needless lookup proliferation.

04

Review normalized schemas for lifecycle, performance, security, and usability.

Normalization cannot fix wrong requirements

Suppose the model says each Asset has exactly one owner forever. You can normalize that model perfectly and still be wrong if ownership changes over time or co-ownership exists.

First principle

A normalized implementation of an incorrect domain model is still incorrect.

Wrong entity boundaries

Imagine Person and Customer are modeled as separate entities even though Customer is merely a role a Person or Organization can play. The tables may each be in 3NF yet duplicate identities and create synchronization problems.

Over-normalized lookup tables

Some designs create a table for every tiny code:

model · example
YesNoLookupGenderLookupBooleanLookupPriorityLookupSortDirectionLookup

Formal normalization does not require a separate relation for every finite domain. A check constraint or domain type may be simpler when values have no independent metadata or lifecycle.

Excessive one-to-one fragmentation

A design may split one concept across many 1:1 tables:

model · example
CustomerCoreCustomerNameCustomerStatusCustomerCreatedAtCustomerPreferences

All tables can be normalized while the design becomes expensive to query and difficult to understand. Split for meaningful lifecycle, security, optionality, scale, or subtype reasons—not mechanically.

Missing historical semantics

A 3NF Asset table with:

model · example
asset_idcustomer_id

may correctly represent current ownership but cannot answer who owned the asset last year. If history is a requirement, normalization alone will not invent temporal structures.

Missing transaction semantics

Normalized tables can still permit inconsistent multi-table states if transaction boundaries are poorly designed. For example, WorkOrder may be marked closed while an active assignment remains open unless the close operation enforces all required invariants atomically.

Performance is a separate dimension

A normalized OLTP schema may require joins for common reads. That is often acceptable and indexable. In other workloads, deliberate denormalization, materialized views, caches, or star schemas may be justified.

The important point is to denormalize intentionally after understanding the source-of-truth model and consistency cost.

Normalized but poorly indexed

3NF says nothing about indexes. A perfectly normalized WorkOrder table with no useful index on asset_id may perform poorly for asset-history queries.

Normalized but insecure

Normal forms do not prevent:

  • storing unnecessary sensitive data;
  • cross-tenant references;
  • weak authorization boundaries;
  • overly broad database privileges;
  • retaining personal data longer than necessary.

Normalized but badly named

model · example
T1(id, x, y)T2(id, t1_id, z)

can be normalized and still be almost useless to humans. Naming remains part of design quality.

Normalized but missing constraints

This relation can be structurally normalized:

model · example
PartUsage(  part_usage_id,  work_order_id,  part_id,  quantity)

but still allow negative quantities or references to nonexistent parts if constraints are absent.

Normalized but wrong grain

Suppose PartUsage intends one row per individual inventory issue, but the key enforces only one row per work_order + part. The relation can look normalized while collapsing multiple events into one aggregate fact.

Normalization and reporting grain

Normalized schemas often contain several child relations. Joining them carelessly can multiply rows. Reporting models need explicit grain, aggregation strategy, and semantic layers.

When denormalization is valid

Examples:

  • precomputed summary totals;
  • materialized views;
  • read-optimized search documents;
  • warehouse fact/dimension models;
  • immutable event snapshots.

But every duplicate fact needs an owner and refresh strategy.

Design review after normalization

DimensionQuestion
SemanticsDoes each relation represent the right real-world concept and grain?
IntegrityAre keys, FKs, checks, and cross-row rules enforceable?
HistoryCan required past states be reconstructed?
PerformanceDo critical access paths have suitable indexes or projections?
SecurityAre ownership, tenancy, and sensitive data modeled safely?
EvolutionCan the schema change without destructive migrations?
UsabilityCan developers and analysts understand and query it correctly?

WorkshopHub example: normalized but incomplete

Assume these 3NF tables exist:

model · example
CustomerAssetWorkOrderTechnicianWorkOrderAssignmentPartPartUsageWorkOrderStatus

Open questions still include:

  • Does Asset ownership require history?
  • Can technician assignments overlap?
  • Who is allowed to close a work order?
  • How are status transitions audited?
  • What indexes support common queries?
  • How are soft deletion and retention handled?

Do not normalize beyond useful semantics

Normalization is not a contest to maximize table count. The objective is to represent independent facts cleanly and reduce harmful redundancy while preserving understandable, enforceable, performant semantics.

Chapter 8 final checkpoint

Critique a normalized schema

A system has 3NF tables User, Organization, Membership, Role, Status, Country, Currency, and Address. Yet every API request requires 12 joins, membership history is overwritten, tenant IDs are not part of foreign-key constraints, and Address rows cannot represent effective dates.

Is the schema “good” because it is normalized?

Review answer

No. It may satisfy dependency-oriented normal forms while failing performance, history, tenancy integrity, and temporal semantics. Normalization is one correctness dimension, not the full definition of a production-ready design.

Summary and next chapter

Chapter 8 applied 1NF, 2NF, and 3NF from structural foundations through dependency-based decomposition, then showed their limits. Chapter 9 goes deeper into advanced normalization: BCNF, multivalued dependencies and 4NF, join dependencies and 5NF, reference-data design, and choosing a practical normal form.

References

  • C. J. Date, Database Design and Relational Theory.
  • Martin Kleppmann, Designing Data-Intensive Applications.
  • Ramez Elmasri and Shamkant B. Navathe, Fundamentals of Database Systems.
  • Martin Fowler, Patterns of Enterprise Application Architecture.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.