0
0
LLDsystem_design~7 mins

Immutability for safety in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
When multiple parts of a system share data that can change, unexpected bugs happen because one part changes data while another part is still using it. This causes crashes, inconsistent results, and hard-to-find errors, especially in concurrent or multi-threaded environments.
Solution
Immutability means data cannot be changed after creation. Instead of modifying existing data, new copies are made with changes. This prevents accidental changes and race conditions because shared data stays constant and safe to read by anyone at any time.
Architecture
Immutable Obj
(unchanged)
Reader 1
New Immutable
Obj (copy +

This diagram shows an immutable object shared safely by multiple readers. When changes are needed, a new immutable object is created instead of modifying the original.

Trade-offs
✓ Pros
Prevents bugs from unexpected data changes in concurrent environments.
Simplifies reasoning about program state since data never changes.
Enables safe sharing of data without locks or synchronization.
Facilitates undo/redo and time-travel debugging by keeping old versions.
✗ Cons
Can increase memory usage due to creating copies instead of modifying in place.
May cause performance overhead if large data structures are copied frequently.
Requires careful design to avoid excessive copying in performance-critical paths.
Use when your system has concurrent reads and writes to shared data or when safety and predictability are critical, especially in multi-threaded or distributed systems.
Avoid when working with very large mutable data that changes frequently and performance or memory is a strict constraint, and concurrency is not a concern.
Real World Examples
Google
Uses immutable data structures in their MapReduce framework to safely share data between distributed tasks without synchronization overhead.
Facebook
React library uses immutable state updates to efficiently detect changes and avoid bugs in UI rendering.
Twitter
Employs immutable messages in their distributed messaging system to ensure message integrity and safe concurrent processing.
Code Example
The before code shows a mutable UserProfile object that can be changed by any part, risking inconsistent state. The after code uses a frozen dataclass to make UserProfile immutable. Updates create new copies with changes, ensuring safety and predictability.
LLD
### Before (mutable shared state, unsafe)
class UserProfile:
    def __init__(self, name, age):
        self.name = name
        self.age = age

profile = UserProfile("Alice", 30)

# Multiple parts modify the same object
profile.age += 1  # Part A
profile.name = "Alicia"  # Part B

### After (immutable data, safe)
from dataclasses import dataclass, replace

@dataclass(frozen=True)
class UserProfile:
    name: str
    age: int

profile = UserProfile("Alice", 30)

# To update, create a new object
new_profile = replace(profile, age=profile.age + 1)
newer_profile = replace(new_profile, name="Alicia")
OutputSuccess
Alternatives
Lock-based synchronization
Allows mutable shared data but uses locks to control access and prevent concurrent modifications.
Use when: Choose when data changes are frequent and copying is too costly, but you can tolerate complexity and potential deadlocks.
Copy-on-write
Shares data until a write occurs, then copies only the part that changes, reducing full copies.
Use when: Choose when writes are rare compared to reads, to optimize memory and performance.
Summary
Immutability prevents bugs by ensuring data cannot change unexpectedly after creation.
It enables safe sharing of data in concurrent systems without locks or synchronization.
The trade-off is increased memory use and potential performance costs from copying data.