The tool was never wrong, the shape of the state was
The tool was never wrong. The shape of the state was.
TECHNICALI stopped asking "NgRx or Signals or RxJS." I started asking "what shape is this state."
Three tools get lumped into one conversation because they all touch state in Angular. In practice they solve different problems. Pick the wrong one and you feel it later: extra boilerplate, a bug that only shows up under load, a debug session that takes an hour longer than it should.
I still reach for RxJS for streams. HTTP requests that need retry logic, debounced search input, websocket messages, anything that arrives over time and needs to be combined, cancelled, or transformed before it reaches a component. If the data has a timeline, RxJS is still the right tool, and these days it's usually one toSignal() away from wherever it needs to land.
Signals are for state a component or a small feature actually owns. A toggle, a form value, a computed total, a loading flag. Local, synchronous, no subscription to manage, no unsubscribe to forget. This is where most of my new code lives now, not because Signals is trendy, but because most component state was never a stream to begin with.
NgRx is for state that many unrelated parts of the app need to read and change, with a history of how it got there. Cross-feature state, anything you need to replay in DevTools to see who changed it and why. Half the NgRx stores I've reviewed this year didn't need to exist. The state they held never left one feature.
The mistake I made for years wasn't picking the wrong tool. It was forcing every kind of state through the one I'd already picked.
A stream flattened into a signal too early, losing its timing. A toggle wrapped in an NgRx action, dispatched and reduced for something that never left one component.
The tool was never wrong. The shape of the state was.
So the real question was never which tool wins.
What's the thing in your codebase right now that's using the wrong one of these?
RxJS, Signals, and NgRx solve different problems. Picking the wrong one is where the boilerplate and the bugs come from.
