The 5 RxJS Operators That Cover 90% of Real Work RxJS has over a hundred operators, and that's exactly why most teams end up in one of two bad places. Either they avoid it entirely, handling async events with manual subscriptions and hand-rolled flags — or they drown in an operator library too big to hold in their head, reaching for whatever half-remembered name sounds right. Neither is necessary. In real, everyday frontend work, five operators cover the overwhelming majority of what actually comes up. Learn what problem each one names, and the rest of the library becomes optional reading instead of a wall to climb. The five, and the problem each one names 1. — cancel-and-replace Reach for this when a new event should make the previous async operation irrelevant. The textbook case is a search box: the user types "rea", your app fires a request, then they type "react" a moment later. cancels the first request's subscription and switches to the new one — so a slow response to "rea" can never overwrite the correct result for "react". 2. — rate-limit before acting Reach for this when a source fires rapidly but you only care about the value once things settle. Keystrokes are the classic case — you don't want to search on every character, only once the user pauses. Notice these two compose directly — debounce first, then cancel-and-replace. That pairing alone covers most "search-as-you-type" features end to end. 3. — derive one value from several sources Reach for this when a piece of UI depends on more than one independent stream at once — a filtered list that depends on both a search term and a category dropdown, neither of which waits for the other. 4. — recover without killing the stream Reach for this the moment any stream can fail from a source you don't control — an HTTP call, in practice, always. Without it, one error terminates the observable permanently — no more values will ever come through, even after the underlying problem is fixed. 5. — share one execution among multiple subscribers Reach for this when more than one part of the app subscribes to the same source, and you don't want the underlying work — an HTTP call, a WebSocket connection — to run once per subscriber. Without it, every in every template re-triggers the whole operation independently. The principle that transfers None of this is really about RxJS syntax. It's a taxonomy of five problems that show up in any reactive UI, regardless of framework: cancellation (don't let a stale response win), rate-limiting (don't act on every intermediate event), combination (derive one value from several independent sources), recovery (one failure shouldn't kill everything downstream), and sharing (don't redo the same work for every consumer). React doesn't have these as named operators, but it faces the identical five problems. Cancellation is an passed into , checked in a cleanup function. Rate-limiting is a hand-rolled or library hook. Combination is deriving one value from several pieces of state. Recovery is a around an async call, or an error boundary. Sharing is exactly what a library like TanStack Query exists to do — one cached result serving every component that asks for it. The operators aren't Angular trivia. They're names for problems you'll solve one way or another, in every framework, whether or not you have a word for them. The Trade-off: Are Operators Actually Worth Learning by Name? Writing a manual subscribe with an if-check feels faster than pausing to remember an operator's name. Whether that's true depends entirely on what the feature grows into. The pain, concretely A typeahead search feature degrades the same way almost every time: v1: A single fires a search on every keystroke. Ships fast, looks fine in the demo. v2: QA notices that typing quickly sometimes shows results for an old, shorter search term after the results for the real term have already arrived — a slower request for "rea" resolved after the faster request for "react". The fix: a manually tracked variable, incremented on each keystroke and checked in the response handler before rendering. v3: Product asks for a category filter that also triggers a re-search. Now there are two independent triggers writing to the same tracking logic, and the manual bookkeeping has to account for both. v4: A slow connection surfaces a bug: when the request fails, the observable dies silently, and the search box stops responding to any further typing until the page is refreshed — because nothing ever re-subscribed after the unhandled error terminated the stream. Nothing in that sequence was a bad engineer's mistake. It's what happens when five well-known problems — cancellation, combination, recovery — get reinvented by hand, one ad hoc flag at a time, instead of named and solved with the operator built for exactly that job. Side-by-side Manual subscribe + hand-rolled flags Named operators --- --- --- Stale response arrives after a newer one Manual bookkeeping, checked everywhere a re…