---
title: Angular 16 Just Dropped a Long Overdue Feature
description: Angular 16 features a new takeUntilDestroyed operator, solving the long-standing challenge of preventing memory leaks in RxJS subscriptions.
image: https://www.bitovi.com/hubfs/Angular%2016%20Just%20Dropped%20a%20Long%20Overdue%20Feature-1.png
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

[ Angular ](https://www.bitovi.com/blog/topic/angular) |  May 9, 2023

# Angular 16 Just Dropped a Long Overdue Feature

 Angular 16 features a new takeUntilDestroyed operator, solving the long-standing challenge of preventing memory leaks in RxJS subscriptions.

![Mark Thompson](https://www.bitovi.com/hubfs/People/mark-thompson.jpg)

 Mark Thompson

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

The Angular team just released an exciting [new major version of Angular](https://blog.angular.io/angular-v16-is-here-4d7a28ec680d) that comes with many new features. One of these features has been something that the Angular community has wanted for a long time, and we've inched closer and closer with each major version. I'm talking about the `takeUntilDestroyed` operator.

### Wait... Is This More Important Than Signals?

Maybe this feature isn't as impactful as [Signals](https://github.com/angular/angular/tree/main/packages/core/src/signals#angular-signals-implementation), but `takeUntilDestroyed()` solves a problem that the Angular community has trying to solve for years: what is the "cleanest" pattern for preventing memory leaks when using RxJS?

Want to learn more about preventing memory leaks and other must-knows for optimizing your Angular application's performance? Check out our blog post that lists [5 Essential Tips to Improve Angular App Performance](https://www.bitovi.com/blog/5-essential-tips-to-improve-angular-app-performance)

For a long time, the Angular community has been split on what is the best way to deal with cleaning up subscriptions when using RxJS. When the `async` pipe is out of the question, there are two popular solutions:

1. Using the `unsubscribe()` or SubSink pattern
2. Using the `takeUntil()` pattern

Both solutions look somewhat similar and have led to many debates over the years.

### The unsubscribe() or SubSink Pattern

The "unsubscribe" or SubSink pattern is the concept of storing a reference to all subscriptions and using the `unsubscribe` method in the `OnDestroy` lifecycle hook:

```
import { Component } from '@angular/core';import { Subscription, Observable } from 'rxjs';@Component({/* ... */})export class MyComponent {    foo$: Observable<Foo> = this.bar();    subscriptions = new Subscription();    constructor() {        this.subscriptions.add(this.foo$.subscribe());    }    ngOnDestroy(): void {        this.subs.unsubscribe();    }}
```

 

Although this pattern works as expected, usage of the SubSink pattern tends to draw controversy for not being declarative, which is why developers have argued to use the `takeUntil` pattern.

### The takeUntil() Pattern

The "takeUntil" pattern is the concept of creating a Subject and using the `takeUntil` operator to complete subscriptions by calling `next()` and following up with `complete()` to clean up the Subject itself in the OnDestroy lifecycle hook:

```
import { Component } from '@angular/core';import { takeUntil, Observable, Subject } from 'rxjs';@Component({/* ... */})export class MyComponent {    foo$: Observable<Foo> = this.bar();    unsubscribe$ = new Subject<void>();    constructor() {        this.foo$.pipe(            takeUntil(this.unsubscribe$)        ).subscribe();    }    ngOnDestroy(): void {        this.unsubscribe$.next();        this.unsubscribe$.complete();    }}
```

 

Despite both patterns working as expected, developers have been in search of a way to avoid having to use the OnDestroy lifecycle hook in hopes of less boilerplate in their code.

This inspiration birthed many libraries such as [ngx-auto-unsubscribe](https://github.com/NetanelBasal/ngx-auto-unsubscribe) and [@ngneat/until-destroy](https://github.com/ngneat/until-destroy) which utilizes decorators. While these solutions are valid, they either still require the `OnDestroy` lifecycle hook or required knowledge of how decorators might interfere with Angular's internal decorators.

### Everything Changed When Angular 14 Released

When Angular 14 released, the `inject()` helper function could now be used in components which gave us a way to create a custom RxJS operator for cleaning up subscriptions:

```
import { inject } from '@angular/core';export function takeUntilDestroyed<T>(): UnaryFunction<Observable<T>, Observable<T>> {  const viewRef = inject(ChangeDetectorRef) as ViewRef;  const unsubscribe$ = new ReplaySubject<void>(1);  viewRef.onDestroy(() => {    unsubscribe$.next();    unsubscribe$.complete();  });  return (observable: Observable<T>) => observable.pipe(takeUntil(unsubscribe$));}
```

Now developers had a simple way to avoid the OnDestroy lifecycle hook without needing custom decorators:

```
import { Component } from '@angular/core';import { takeUntilDestroyed } from '../operators/take-until-destroyed';import { Observable } from 'rxjs';@Component({/* ... */})export class MyComponent {    foo$: Observable<Foo> = this.bar();    constructor() {        this.foo$.pipe(            takeUntilDestroyed()        ).subscribe();    }}
```

This was great! And so far was the "cleanest" way to manage subscriptions. The only issue now was that developers had to write this custom RxJS operator in their codebase or import a library that implemented it... until Angular 16 was released.

### Now takeUntilDestroyed() Comes Out of the Box

With the release of Angular 16, the `takeUntilDestroyed` operator is now [shipped with Angular](https://github.com/angular/angular/pull/49154/files#diff-508a78c7ae7456260190375c3b624cdd2fd5219aee48375c9d848ea2f3f95395R23) and is a [fully documented](https://github.com/angular/angular/pull/50042/files#diff-956acddee849d61cffeefd1cc53f148873e8771d46d86fd6f5e945df6092e7c1R102) feature of Angular as part of the [RxJS Interop package](https://angular.io/guide/rxjs-interop) developer preview:

```
import { Component } from '@angular/core';import { takeUntilDestroyed } from '../operators/take-until-destroyed';import { Observable } from 'rxjs';@Component({/* ... */})export class MyComponent {    foo$: Observable<Foo> = this.bar();    constructor() {        this.foo$.pipe(            takeUntilDestroyed()        ).subscribe();    }}
```

### Conclusion

This might not be the flashiest feature to come to Angular, but it is something that has been requested for many major versions. It's great to see that Angular is improving with each major version.

### What Do You Think?

Is your team stuck on an older version of Angular and missing out on all these features? Don't hesitate to [schedule a free consultation call](https://www.bitovi.com/services/frontend/angular-consulting) if you need any assistance upgrading to Angular 16. Our team is always here to support you.

Maybe you have a better pattern for preventing memory leaks when using RxJS. Join our [Community Discord](https://discord.gg/J7ejFsZnJ4) and share your feedback with us on the #Angular channel.

[![Join our Discord](https://no-cache.hubspot.com/cta/default/2171535/224f5741-883f-452d-b142-dd575d07685e.png)](https://cta-redirect.hubspot.com/cta/redirect/2171535/224f5741-883f-452d-b142-dd575d07685e)

 Previous Post

![Conflict-Free Leadership: The Framework in Action [Part 5]](https://www.bitovi.com/hs-fs/hubfs/Conflict-Free%20Leadership-%20The%20Framework%20in%20Action%20%5BPart%205%5D.png?height=117&name=Conflict-Free%20Leadership-%20The%20Framework%20in%20Action%20%5BPart%205%5D.png) [ Conflict-Free Leadership: The Framework in Action [Part 5] ](https://www.bitovi.com/blog/conflict-free-leadership-framework-in-action)

  

 Next Post

![New in Vue.js 3.3: Two-Way Binding With defineModel Macro](https://www.bitovi.com/hs-fs/hubfs/New%20in%20Vue.js%203.3-%20Two-Way%20Binding%20With%20defineModel%20Macro.png?height=117&name=New%20in%20Vue.js%203.3-%20Two-Way%20Binding%20With%20defineModel%20Macro.png) [ New in Vue.js 3.3: Two-Way Binding With defineModel Macro ](https://www.bitovi.com/blog/new-in-vue-3.3-two-way-binding-with-definemodel-macro)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/angular-16-just-dropped-a-long-overdue-feature",
    "@type" : "WebPage",
    "description" : "Angular 16 features a new takeUntilDestroyed operator, solving the long-standing challenge of preventing memory leaks in RxJS subscriptions."
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Mark Thompson"
  },
  "dateModified" : "October 3, 2023, 7:40:44 PM",
  "datePublished" : "2023-05-09 17:48:46",
  "description" : "Angular 16 features a new takeUntilDestroyed operator, solving the long-standing challenge of preventing memory leaks in RxJS subscriptions.",
  "headline" : "Angular 16 Just Dropped a Long Overdue Feature",
  "image" : {
    "@type" : "ImageObject",
    "url" : "https://www.bitovi.com/hubfs/Angular%2016%20Just%20Dropped%20a%20Long%20Overdue%20Feature-1.png"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```