CONCEPT 11 · FOUNDATIONS
Immutable Data & Structural Sharing
"Never modify — create a new version with the change."
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?