Skip to content

Signals vs RxJS

They are complementary, not rival teams.

Question Signal Observable
What is the current value? natural may require replay/current-value convention
Synchronous derivation computed operator pipeline works but may be heavier
Async sequence over time limited alone core strength
Cancellation/concurrency not encoded by value higher-order operators encode policy
Template read call signal AsyncPipe or bridge
Error/completion channels no yes
Dependency tracking automatic on reads explicit stream graph

Choose signals when

  • state has a meaningful current synchronous value;
  • UI derives values from other state;
  • local/store updates are commands;
  • fine-grained template consumption helps clarity.

Choose RxJS when

  • multiple async events must be combined;
  • cancellation, ordering, buffering, retries, or time matters;
  • integrating router, forms, WebSocket, or HTTP streams;
  • error and completion semantics are meaningful.

Bridge at ownership boundaries

Use toSignal when a component/store owns an observable and consumers need current state. Use toObservable when a signal must enter temporal operator composition. Avoid repeated back-and-forth conversion.

Common mistakes

  • using an effect to copy one signal into another;
  • subscribing inside subscribing instead of selecting flattening semantics;
  • turning every event into a global subject;
  • keeping server cache as an unbounded root signal without invalidation;
  • claiming observables are obsolete because signals render conveniently.

Decision challenge

Before reading the example, classify completion percentage, typeahead requests, server cache, route parameters, and a websocket feed by owner, current-value semantics, time, error, completion, and concurrency needs. Implement one boundary in Signals and state and RxJS reasoning.

A strong explanation starts with semantics, not preference: “Completion percentage is synchronous derived state, so computed is appropriate. Typeahead requests require debounce and cancellation, so RxJS with switchMap expresses the policy. I bridge the result once into signal-based view state.”