DEV Community

Cover image for RxJS Subjects in the Angular Signals Era: Obsolete or Still Powerful?
Mayuri Jha
Mayuri Jha

Posted on

RxJS Subjects in the Angular Signals Era: Obsolete or Still Powerful?

For years, Angular developers lived in a world powered by RxJS.

Streams, subscriptions, operators, Subjects — if you wanted reactive behavior in Angular, RxJS was the way.

Then Angular introduced Signals, a new reactivity model that promised something developers had been craving:

Simpler state management with less boilerplate.

Suddenly, many Angular developers began asking:

  • Do we still need RxJS Subjects?
  • Are Signals replacing RxJS?
  • Should we rewrite everything?

Before we panic-delete our Subject imports, let's understand what actually changed.


A Quick Mental Model

Think of it like this:

Signals are like a spreadsheet cell.

When a value changes, everything depending on it updates automatically.

RxJS is like a pipeline of events.

Data flows through operators, transformations, and async processes.

Both are reactive — but they solve different problems.


The Old Angular Pattern: RxJS Everywhere

Before Signals, developers often used BehaviorSubject even for simple component state.

Example:

private countSubject = new BehaviorSubject<number>(0);
count$ = this.countSubject.asObservable();

increment() {
  this.countSubject.next(this.countSubject.value + 1);
}
Enter fullscreen mode Exit fullscreen mode

Template:

{{ count$ | async }}
Enter fullscreen mode Exit fullscreen mode

For beginners, this raised questions like:

  • Why do I need BehaviorSubject?
  • Why asObservable()?
  • Why the async pipe?

A lot of code… for something as simple as a counter.


The Signals Way

Now the same example becomes:

count = signal(0);

increment() {
  this.count.update(v => v + 1);
}
Enter fullscreen mode Exit fullscreen mode

Template:

{{ count() }}
Enter fullscreen mode Exit fullscreen mode

That's it.

  • No subscriptions.
  • No async pipe.
  • No Subject.

This is where Signals shine.

Where Signals Truly Replace RxJS Subjects

Signals are fantastic for application state.

1. Component State

Instead of:

loading$ = new BehaviorSubject(false);
Enter fullscreen mode Exit fullscreen mode

You can simply write:

loading = signal(false);
Enter fullscreen mode Exit fullscreen mode

2. Derived State

Previously:

total$ = combineLatest([price$, quantity$]).pipe(
  map(([p, q]) => p * q)
);
Enter fullscreen mode Exit fullscreen mode

With Signals:

total = computed(() => price() * quantity());
Enter fullscreen mode Exit fullscreen mode

This reads almost like plain English.

3. UI Reactivity

Signals integrate directly with Angular change detection.

Update the signal → UI updates automatically.

No subscriptions needed.

But Signals Don't Replace Everything

Here's where beginners often misunderstand.

Signals manage state.
RxJS manages streams.

Those are different things.

Where RxJS Subjects Are Still the Better Choice

1. Event Streams

Imagine a chat application receiving messages.

messages$ = new Subject<Message>();

socket.onmessage = msg => {
  this.messages$.next(msg);
};
Enter fullscreen mode Exit fullscreen mode

This is a stream of events, not a single state value.

Signals are not designed for this pattern.

2. Complex Async Workflows

Consider a search box.

You want to:

  • debounce typing
  • cancel previous requests
  • fetch new results

RxJS handles this beautifully:

search$
  .pipe(
    debounceTime(300),
    switchMap(query => this.http.get(`/api?q=${query}`))
  )
  .subscribe();
Enter fullscreen mode Exit fullscreen mode

Signals do not provide operators like:

  • debounce
  • switchMap
  • retry
  • merge streams

That is RxJS territory.

3. WebSockets & Real-Time Data

Live data streams fit RxJS naturally.

Examples include:

  • stock price feeds
  • live chat
  • multiplayer game updates

Signals are state holders, not event streams.

The Best Approach: Use Both

The Angular team never intended Signals to replace RxJS.

Instead, they built tools to connect them together.

Observable → Signal

users = toSignal(this.http.get<User[]>('/api/users'));
Enter fullscreen mode Exit fullscreen mode

Now your template can simply use:

{{ users()?.length }}
Enter fullscreen mode Exit fullscreen mode

Signal → Observable

user$ = toObservable(userSignal);
Enter fullscreen mode Exit fullscreen mode

Useful when integrating with RxJS pipelines.

A Practical Architecture

Modern Angular apps often follow this pattern:

Signal and Subject in modern Angular

RxJS handles data flow.

Signals handle UI state.

When to Use Signals

Use Signals when dealing with:

  • component state
  • UI state
  • derived values
  • reactive templates
  • replacing BehaviorSubject in components

When to Use RxJS Subjects

Use Subjects when dealing with:

  • event streams
  • async workflows
  • WebSockets
  • complex operator chains
  • cancellation logic

My Take

Angular development is evolving toward something simpler:

  • Less boilerplate
  • Clearer reactivity
  • Better separation between state and streams

In many cases, Signals can replace BehaviorSubject when managing simple component or service state.

However, RxJS remains incredibly powerful for:

  • asynchronous streams
  • event pipelines
  • complex reactive workflows

Signals didn't replace RxJS.

They just gave Angular developers the right tool for the right job.

Top comments (0)