CONCEPT 11 · FOUNDATIONS

Immutable Data & Structural Sharing

"Never modify — create a new version with the change."

immutabilitydata structuressharing
Plain English

Immutable data structures never change after they're created. Instead of modifying them in place, you create a new version with the change applied. The secret to their performance is structural sharing: the new version shares all unchanged parts with the old version. Only the changed path creates new objects — nothing gets copied wholesale.

Analogy

Git commits. When you commit a change to 3 files out of 10,000, git doesn't copy the other 9,997 — they're shared with the previous commit via the object tree. Only the changed files and their parent directory nodes become new objects. Immutable data structures work identically: share unchanged parts, create new nodes only for what changed.

You already know this
React setState / useReducer — always pass a new object, never mutate state directlySpread operator: {...user, name: "Bob"} — new object sharing all unchanged fieldsImmer's produce() — writes feel mutable but Immer creates a new immutable snapshotRedux — every action produces a new state; you can replay the full historyGit — every commit is an immutable snapshot; history is never lost
Code Example
JavaScript
// MUTABLE — modifying in place (dangerous)
const user = { name: 'Alice', role: 'viewer', age: 30 };
function promoteUser(u) {
  u.role = 'admin'; // mutates the original!
  return u;
}
const promoted = promoteUser(user);
console.log(user.role);     // 'admin' — original changed!
console.log(promoted === user); // true — same object

// IMMUTABLE — structural sharing
function promoteUser(u) {
  return { ...u, role: 'admin' }; // new object, shares name and age
}
const promoted = promoteUser(user);
console.log(user.role);          // 'viewer' — original safe
console.log(promoted.role);      // 'admin'
console.log(promoted === user);  // false — different objects

// Structural sharing in action (linked list):
// Original: A(1) → B(2) → C(3)
// Prepend 0: D(0) → A(1) → B(2) → C(3)
// Nodes A, B, C are SHARED — nothing was copied

// This is why React + Redux are fast despite "copying" state:
function reducer(state, action) {
  switch (action.type) {
    case 'UPDATE_NAME':
      // Only 'name' is new; all other fields are shared
      return { ...state, name: action.name };
    default:
      return state; // same reference — no copy at all
  }
}
Apply when
Undo/redo features — keep a list of state snapshots; immutability makes this free
Time-travel debugging (Redux DevTools) — replay any past state exactly
Concurrent reads — multiple threads can read the same immutable value simultaneously with no locks
Caching — immutable values can be safely cached and shared because they can never change
Any time a bug might be caused by shared mutable state — make it immutable and the bug disappears
Check Your Understanding
You have a tree with 50,000 nodes. You update one leaf. With structural sharing, how many new nodes are created?