Observer Pattern Explained: Reacting to State Changes Without Tight Coupling
How the observer pattern works — subjects, observers, event-driven updates, and why it underpins reactive UIs, event buses, and pub/sub systems.
Observer Pattern
The observer pattern defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically.
What It Really Means
Imagine a spreadsheet. Cell A1 contains a value. Cell B1 contains a formula that references A1. Cell C1 contains another formula referencing A1. When you change A1, both B1 and C1 update automatically. You did not explicitly tell B1 and C1 to recalculate — they are observing A1 and react to its changes.
This is the observer pattern. The subject (A1) maintains a list of observers (B1, C1) and notifies them whenever its state changes. The subject does not need to know what the observers do with the notification — it just broadcasts the change. This decouples the object that changes from the objects that react to the change.
The observer pattern is one of the most widely used design patterns in software. React's state management, DOM event listeners, RxJS observables, Node.js EventEmitter, and distributed pub/sub systems are all variations of the same idea: register interest in a subject, get notified when something happens.
How It Works in Practice
Classic Structure
Push vs Pull Model
Push model: The subject sends the changed data to observers.
Pro: Observer has all the data it needs. Con: Subject must know what data observers want.
Pull model: The subject notifies observers, who then query the subject for data they need.
Pro: Subject is simpler. Con: Multiple round-trips if observers need different data.
Real System Examples
DOM Event Listeners (Browser):
React State Updates:
Implementation
Classic observer pattern (Python):
Event emitter pattern (TypeScript):
Trade-offs
Benefits:
- Open/Closed Principle: add new observers without modifying the subject
- Loose coupling: subject knows observers only through an interface
- Supports broadcast communication: one change triggers multiple reactions
- Foundation for reactive and event-driven programming
Costs:
- Memory leaks: if observers are not detached, they persist in the subject's list (common in UI frameworks)
- Unexpected cascades: Observer A modifies state that triggers Observer B, which triggers Observer C — hard to debug
- Ordering dependency: if observers must execute in a specific order, the pattern breaks down
- Performance: notifying hundreds of observers synchronously blocks the subject
When to use:
- UI state management (React, Vue, Angular)
- Event-driven architectures within a single process
- Decoupling components that react to shared state changes
- Building custom event systems
When to avoid:
- When you need guaranteed delivery (use a message queue instead)
- When observer execution order matters (use a pipeline or chain of responsibility)
- When the number of observers is very large (use a pub/sub system with proper message brokering)
Common Misconceptions
- "Observer pattern and pub/sub are the same" — The observer pattern is an in-process design pattern where subjects know their observers directly. Pub/sub is a distributed messaging pattern with a broker in between. Pub/sub is the distributed evolution of the observer pattern.
- "Observers are always notified synchronously" — The classic pattern is synchronous, but many implementations (RxJS, Node.js EventEmitter with setImmediate) support asynchronous notification.
- "The subject decides what observers do" — The subject only sends a notification. Each observer independently decides how to react. The subject does not know or control the observer's behavior.
- "Observer pattern causes memory leaks" — The pattern does not inherently cause leaks. The problem is forgetting to call detach() when an observer is no longer needed. Modern frameworks handle this with cleanup functions (React's useEffect return, Angular's OnDestroy).
How This Appears in Interviews
- "How does React re-render components when state changes?" — Observer pattern: useState creates a subject, components are observers, setState triggers notification and re-rendering.
- "Design a stock price ticker that updates multiple displays" — Classic observer: price feed is the subject, each display widget is an observer.
- "What is the difference between observer and pub/sub?" — Observer is in-process, direct references. Pub/sub is distributed, broker-mediated, supports durability and delivery guarantees.
- "How do you avoid memory leaks with event listeners?" — Always unsubscribe: removeEventListener, unsubscribe(), useEffect cleanup. Explain WeakRef-based observer lists as an advanced technique.
Related Concepts
- Pub-Sub Pattern — the distributed systems evolution of the observer pattern
- Clean Architecture — observers enable decoupled communication between layers
- SOLID Principles — observer pattern implements the Open/Closed and Dependency Inversion principles
- Interview Questions: Design Patterns
- System Design Interview Guide
- Algoroq Pricing — access all concept deep-dives
GO DEEPER
Learn from senior engineers in our 12-week cohort
Our Advanced System Design cohort covers this and 11 other deep-dive topics with live sessions, assignments, and expert feedback.