RxJS

Always unsubscribe. No exceptions. Debate closed.

So many years with Angular. So many years with RxJS. Yet people still fight over “when NOT to unsubscribe”. Truth is. It’s not even worth the conversation. Just unsubscribe always. Simple. I have recently posted the same advice on my social media(X/LinkedIn). While majority agreed without a doubt. A

Always unsubscribe. No exceptions. Debate closed. — RxJS article by Daniel Glejzner on Angular In Depth
Always unsubscribe. No exceptions. Debate closed. — RxJS article by Daniel Glejzner on Angular In Depth
On this page · 9 sections

Years of Angular. Years of RxJS.

And still, the community keeps debating “when you can skip unsubscribing”.

Here’s the thing — it’s not a debate worth having.

Unsubscribe. Every time. Done.

I shared the same take recently on my social media (X/LinkedIn).

Most people nodded along without hesitation. But around 10% seized the chance to flex their deep expertise on why unsubscribing is not always necessary.

The go-to example they always raise:

  • HttpClient cold observable

I’ve been told that this advice is:

  • Terrible
  • A massive overhead
  • Something people should never follow
  • Flat-out wrong
  • Redundant code
  • Too bold an assumption
  • Something to take up with the Angular Team instead

Yes, technically speaking, HttpClient completes on its own in roughly 99% of cases.

But that doesn’t mean you should go hunting for safe spots where you can skip the unsubscribe just because it’s an HttpClient observable.

The simple why:

  • It makes zero sense as a practice
  • There’s no real overhead — you’re already unsubscribing everywhere else, so it’s muscle memory at this point
  • Consistency beats cleverness, every time
  • Stop wasting brain cycles on when *not* to unsubscribe and focus on what matters
  • Consistency…
  • Consistency…

Need more? The advanced why:

  • Crediting a friend, because I couldn’t have phrased it any better:
Always unsubscribe. No exceptions. Debate closed. — figure 3
  • There’s also a GitHub issue from 2022 where this very question got quietly laid to rest. And when we say “Engineering” responded, we mean actual Angular devs.
Always unsubscribe. No exceptions. Debate closed. — figure 4

source: https://github.com/angular/angular/issues/46542

  • And the new Angular docs make it explicit too:
Once the response returns, Observables from HttpClient usually complete (although interceptors can influence this).
Because of the automatic completion, there is usually no risk of memory leaks if HttpClient subscriptions are not cleaned up. However, as with any async operation, we strongly recommend that you clean up subscriptions when the component using them is destroyed, as the subscription callback may otherwise run and encounter errors when it attempts to interact with the destroyed component.

source: https://angular.dev/guide/http/making-requests#http-observables

So next time a teammate nags you about unsubscribing from HttpClient Observables — or any observable they deem “safe” — you have the receipts.

Still doubtful? Listen to Angular Team’s Alex Rickabaugh

Always unsubscribe. No exceptions. Debate closed. — figure 5

Pro tip: avoid subscribing altogether — push everything through the async pipe.

PS: as of Angular v16, `takeUntilDestroyed()` is the cleanest way to handle unsubscriptions.

UPDATE December 5, 2024.


I was asked a while back to respond to claims that you shouldn’t unsubscribe on component destroy when dealing with:

PUT, PATCH, POST, DELETE

The reasoning goes: if you unsubscribe, you risk cancelling an HTTP request mid-flight when the user navigates away — because the subscription dies with the component. If you let the subscription linger and rely on HttpClient’s automatic completion, the request will eventually finish.

These calls are “one-and-done,” as the argument goes.

Technically, that’s 100% accurate. I fully agree — that’s how it works.

But let’s get real. In production apps, things rarely go as planned. Users bounce around, components get destroyed, requests hang — and your UI ends up in a state you didn’t sign up for.

Here’s why that argument only holds up in demos and lab projects:

Real users are impatient

  • They click, switch tabs, and navigate away faster than your HTTP response can return. If you skip cleanup, you’ll get state updates firing on components that no longer exist.

Consistency matters

  • Treating certain observables differently just adds needless complexity. Apply takeUntilDestroyed everywhere and stop juggling exceptions.

AbortController exists for a reason.

  • Modern JavaScript has AbortController, which cancels HTTP requests cleanly at the browser level. It’s not Angular-specific, but it pairs perfectly with what takeUntilDestroyed achieves.

“One-and-done” is a myth.

  • Backend errors, race conditions, or retries can turn your simple PUT or POST into a debugging rabbit hole.

Value consistency. Value simplicity. Unsubscribe 🤝

Tagged in:

Articles

Last Update: December 05, 2024

DG
Daniel Glejzner

Writes about General, News, Signals. Active 2023–2026.

All 77 articles →