
Migrating from RxJS to Signals in Angular? This guide breaks down common patterns, practical tips, and step-by-step strategies to help you transition smoothly from reactive streams to a signals-based architecture.
Alain Chautard
May 5, 2026
RxJS has been around for a long time in Angular applications, which means migrating to signals can seem daunting at first. In this post, I'll cover common patterns, tips, and tricks for migrating your application from RxJS-based to Signal-based in a step-by-step fashion.
First and foremost, the Angular CLI supports several automated migrations, including ones that will turn your input and output decorators into Signal-friendly code, as well as ViewChild content queries.
Here are the commands you need to run:
ng generate @angular/core:signal-input-migration
ng generate @angular/core:output-migration
ng generate @angular/core:signal-queries-migration
If you're using Reactive Forms or other APIs that return Observables, you're one function call away from turning them into Signals:
// Before
data$ = this.http.get(this.API_URL);
// Converting to Signal
data = toSignal(this.data$);
PRO TIP: The above code will create a Signal that has an undefined value initially (Signal<DataType | undefined>), which is hard to work with, as you'll need to check for undefined values with conditions such as @if, data?.property, or data?. something ?? "defaultValue".
You can eliminate such complexity by providing a good default value to toSignal. For instance, if you expect an array of values, a good default value would be an empty array .
Here is an example where I expect a simple object and provide a meaningful default value instead:
// Without default value
rates: Signal<Rates | undefined> = toSignal(this.rates$);
// With default value
rates: Signal<Rates> = toSignal(this.rates$,
{initialValue: {USD: 1, EUR: 1, GBP: 1}}
);

Note that HTTP requests can be replaced with rxResource or httpResource (full HTTP resource tutorial here), but these APIs are still experimental at the time of this writing and thus not recommended for production use yet.
We can convert Subjects to Signals using toSignal(), but removing the Subject entirely is even easier:
// Subject version
currentCurrency = new BehaviorSubject<CurrencySymbol>(DEFAULT_CURRENCIES[0]);
// Signal version
currentCurrency = signal<CurrencySymbol>(DEFAULT_CURRENCIES[0]);
Almost all RxJs operators that combine Observables can be replaced with a computed signal that combines Signals.
Here is an example where I want to get the exchange rate for the currently selected currency, all of which are dynamic and can be changed asynchronously:
// RxJs code
currentExchangeRate$ = combineLatest([
this.exchangeRates$,
this.currentCurrency$
]).pipe(
map(([rates, current]) => rates[current.code as keyof ExchangeRates])
);
// Equivalent Signal based version
currentExchangeRate = computed(
() => this.exchangeRates()[this.currentCurrency().code]
);
And yes, the computed version looks much lighter than the RxJs one!
Sometimes though, we want to keep some of the RxJs logic because it works well and uses features that don't have a direct Signal-based equivalent (here timer). In that case, toSignal does the trick to expose a Signal and "hide" our RxJs business logic from components:
// RxJs code
exchangeRates$: Observable<ExchangeRates> = timer(0, 3600000)
.pipe(
switchMap(() => this.http.get<any>(this.API_URL)),
map(data => ({
USD: 1,
EUR: data.rates.EUR,
GBP: data.rates.GBP
}))
);
// Simple Signal conversion with toSignal()
exchangeRates = toSignal(this.exchangeRates$);
For more comparisons, here is a Stackblitz of a service entirely written with Subjects and RxJs operators, and then its equivalent Stackblitz migrated to Signals.
Migrating from RxJS to Angular Signals isn’t a big bang rewrite — and it shouldn’t be. Angular was designed to let both coexist, and that’s a feature, not a compromise.
The pragmatic approach: migrate what’s painful first. Start with BehaviorSubject-based state in services — those are the easiest wins and the most immediate readability improvements: Services only expose signals, which simplifies your components — No more subscriptions, operators, async pipes, etc.
And remember that Signal forms are around the corner (still experimental at the time of this writing), so don't spend too much time migrating Reactive forms just yet.
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Error Handling in Next.js with catchError
Learn why react-error-boundary falls short in the Next.js App Router and how catchError from Next.js 16.2 fixes both framework error propagation and server data refetching with a single function call.
Aurora Scharff
Jun 18, 2026

SEO in Nuxt with @nuxtjs/seo
Set up sitemaps, meta tags, structured data, OG images, and robots.txt in Nuxt with the official SEO module.
Reza Baar
Jun 17, 2026
![What’s the untracked function? [Angular Signals]](/.netlify/images?url=https:%2F%2Fapi.certificates.dev%2Fstorage%2FZzk75tZNAVT5d3GI9TxAD2JwkIFUKavFFj8sC2BL.png)
What’s the untracked function? [Angular Signals]
Learn how Angular's computed() function derives reactive values from signals and why it plays a key role in building high-performance, signal-based applications with cleaner and more predictable state management.
Alain Chautard
Jun 16, 2026