Angular 17+ introduced Signals, causing developers to ask how they compare to Observables—and whether they replace RxJS.
This guide explains the differences clearly and ends with practical error-handling patterns you should use in real projects.
1. What Are Observables? (Short Recap)
Observables are asynchronous data streams from RxJS.
They are ideal for:
HTTP calls
WebSockets
Continuous event streams
Streams requiring operators (filter, map, mergeMap…)
Key characteristics:
Lazy (execute when subscribed)
Multicast/Unicast depending on usage
Can be cancelled
Powerful because of operators
2. What Are Signals? (Short Recap)
Signals in Angular are reactive variables that trigger change detection efficiently.
They are ideal for:
Local component state
Derived reactive values
Simple app-level state stores
Key characteristics:
Synchronous
Pull-based (read when needed)
No “stream” behavior
No need for async pipes (direct reads like
counter())
Example
const count = signal(0);
count.set(5);
console.log(count());
3. Observables vs Signals — When to Use What?
A) Use Observables When You Need Streams
Perfect for:
HTTP requests
WebSocket data
Real-time event listeners
Multiple chained async operations
Retry/backoff logic
They support operators like:
map,switchMap,mergeMapcatchError,debounceTimeforkJoin,combineLatestretry,delay,takeUntil
B) Use Signals When You Need State
Use signals for:
UI state
Filtering / sorting state
Component-level reactive values
Derived state (
computed)Minimal boilerplate
Signals shine for:
Simplicity
Performance
Predictable reactivity
C) Should You Replace Observables With Signals?
NO.
Observables handle asynchronous streams.
Signals handle reactive state.
They complement each other.
You can even convert between them:
toSignal(myObservable$);
toObservable(mySignal);
4. Mixing Observables and Signals (Best Practices)
Best Practice 1: Use Signals for Component State
Example
const users = signal<User[]>([]);
Best Practice 2: Convert HTTP Observables → Signals
Clean approach:
users = toSignal(this.http.get<User[]>('/api/users'));
Best Practice 3: Avoid Signals for Continuous Streams
Bad use case:
Scroll events
Mouse move
WebSockets

Join the conversation! Your thoughts help the community grow.