# 🧠 Database Normalization & Data Integrity Design
I design database structures using normalization to ensure systems remain consistent, maintainable, and scalable as they grow across modules, workflows, and complex business rules.
🎯 How I Think About Database Design
Data issues rarely come from queries —
they come from poor structure.
If data is not designed properly, it leads to:
So I treat normalization as a core system design concern, not just a database concept in Database Management Systems.
🧩 What Normalization Means to Me
I don’t treat normalization as theory.
I treat it as a practical design mindset:
> each piece of data should live in the right place, once, with clear ownership
📐 Normal Forms (How I Apply Them)
I don’t memorize rules — I apply them through design thinking.
1️⃣ First Normal Form (1NF) — Atomic Data
👉 I avoid:
2️⃣ Second Normal Form (2NF) — Full Dependency
👉 I check:
> “Is this field dependent on the whole context or just part of it?”
3️⃣ Third Normal Form (3NF) — No Hidden Dependency
👉 I validate:
> “Does this data belong here, or is it derived from another table?”
🧩 Design Approach
Separation of Responsibilities
I design tables based on business responsibilities, not convenience.
Example: KPI System
👉 Each table owns one responsibility
Master vs Transaction Data
I clearly separate:
👉 This is a direct result of applying normalization
Dependency Awareness
I always validate:
> “Does this field depend on the correct key?”
Example mistake I avoid:
kpi_employees
(
kpi_id,
employee_id,
kpi_name,
kpi_group_name,
target,
actual
)Because:
👉 So they belong in:
🧠 Good Practices I Follow
⚖️ Tradeoff Awareness
👉 I balance both based on system needs
🚀 When I Intentionally Break Normalization
Normalization ensures clean structure —
but real systems also require business correctness over time.
💡 My Principle
> I break normalization only when business logic depends on historical state
📌 Snapshot-Based Design (Real Case)
Example: Expense System
An expense is created based on:
But over time:
👉 If I rely only on normalized configuration tables:
✅ My Approach (Transaction-Level Snapshot)
I do not pollute the expenses table with snapshot columns.
Instead, I preserve business state through transaction-level tables.
1️⃣ Core Expense (Clean Transaction)
expenses
(
id,
uuid,
name,
description,
attributed_employee_id,
submitted_by,
amount,
currency,
submitted_date,
paid_out_status,
paid_out_date,
pl_effective_date,
expense_status,
created_at,
updated_at,
deleted_at
)👉 This table only represents the expense itself.
2️⃣ Approval Snapshot (Key Design)
expense_approvers
(
id,
uuid,
expense_id,
approver_type,
approver_lvl,
approver_id,
status,
approver_reason,
response_date,
created_at,
updated_at
)✔ Derived from:
policy_expense_approvers👉 When an expense is submitted:
So even if:
👉 The expense keeps its original approval flow
3️⃣ File Association (Independent Context)
expense_files
(
expense_id,
file_id,
type
)Linked with:
files
(
id,
uuid,
name,
path,
extension,
size,
...
)👉 Files are stored independently and linked via a pivot table
🎯 Why This Matters
This ensures:
👉 The system reflects:
> what was true when the expense was submitted, not what is true now
⚠️ Important Design Insight
This is controlled denormalization, not poor design.
📌 Practical Approach
I design databases around:
> data ownership, lifecycle, and business boundaries
not just:
💬 Summary
My approach to database normalization focuses on:
At the same time, I:
This ensures systems remain reliable, scalable, and production-ready as they evolve.