Denormalization
0-day streakReview

Your progress

Level 1

0 XP100 XP to level 2
0day streak
0best streak
0topics started
0cards reviewed
    Review cards

    Progress is stored only in this browser. No account is required.

    Normalization vs denormalization: the 60-second story

    Normalization vs denormalization

    “Ordered 12k times” on every dish. Count it live?

    30,000 menu views a second, 40 dishes each, is 14.4 billion index entries a second. A times_ordered column costs 3,000 small updates a second.

    One copy, three bills

    A change becomes 1 + N writes, where N is the fan-out. Readers can see two answers in between. And drifted copies need repair code.

    Joins are slow, so copy?

    Bad: Copy the reviewer’s name

    Adds a rewrite path and stale names for no gain.

    Good: Try an index first

    Most slow joins lack an index. With one, the join is cheap.

    Climb only as far as you must

    1. Generated column: exact, one row
    2. Same transaction or trigger: exact at commit
    3. Materialized view: as fresh as its refresh
    4. CDC or outbox: seconds behind

    Save, then publish: the classic bug

    A deploy kills the process between the two calls. The database says Dosa Point; search says Dosa Corner, forever. Nothing remembers to finish.

    The fix puts the event in the same transaction

    The rename and an outbox row commit together, or neither does. CDC relays it at least once, so consumers must be idempotent and ordered per key.

    ≈ 500/s

    ceiling for increments on one row

    Assume each increment holds the row lock about 2 ms. A one-rupee biryani offer at 3,000 orders a second queues. Sixteen striped slots: ≈ 8,000/s.

    Every copy drifts eventually: a bug, a skipped code path, a failed backfill.

    The plan

    Schedule a drift check and keep a rebuild path. A copy you can’t rebuild is a second source of truth.

    Remember

    Start normalized. Copy only for a measured read, and name the sync path, drift check and rebuild for every copy.