
When working with Angular apps, handling real-time data, user interactions, or shared state is a common challenge. That’s where RxJS shines — especially with tools like Subject
and BehaviorSubject
.
These two are often confused, but once you get the hang of when to use which, it can dramatically improve the way you architect your Angular features.
Let me break it down based on how I’ve used them in real-world projects.
📡 What’s a Subject?
Think of a Subject
as a broadcast channel. It doesn’t remember anything — it just pushes out values to anyone who’s listening at that exact moment.
import { Subject } from 'rxjs';
const subject = new Subject<string>();
subject.subscribe(val => console.log('Subscriber 1:', val));
subject.next('🚀 First Value'); // Only active subscribers receive this
subject.subscribe(val => console.log('Subscriber 2:', val));
subject.next('🔥 Second Value');
What happens:
- Subscriber 1 gets both values.
- Subscriber 2 only gets
🔥 Second Value
.
✔️ When I use Subject:
- For one-off events like button clicks or notifications.
- When the past value doesn’t matter, and I just need to broadcast something.
- In event buses or when triggering side effects.
🔁 What’s a BehaviorSubject?
A BehaviorSubject
is like a Subject
with memory. It always holds the latest value — and any new subscriber will immediately get that value.
import { BehaviorSubject } from 'rxjs';
const behavior = new BehaviorSubject<string>('👋 Initial');
behavior.subscribe(val => console.log('Subscriber 1:', val));
behavior.next('🔄 Updated');
setTimeout(() => {
behavior.subscribe(val => console.log('Subscriber 2 (late):', val));
}, 2000);
What happens:
- Subscriber 1 gets both values.
- Subscriber 2 (joining later) instantly gets the latest:
'🔄 Updated'
.
✔️ When I use BehaviorSubject:
- For state management (like auth, UI state, or cached data).
- When I want components to always have the latest value, even if they subscribe later.
- For services that share data between components.
🧠 A Practical Use Case: Auth State
In one of my apps, I needed to track whether a user was logged in. Here’s how I did it using BehaviorSubject
:
@Injectable({ providedIn: 'root' })
export class AuthService {
private isLoggedInSubject = new BehaviorSubject<boolean>(false);
isLoggedIn$ = this.isLoggedInSubject.asObservable();
login() {
this.isLoggedInSubject.next(true);
}
logout() {
this.isLoggedInSubject.next(false);
}
}
Then, inside a component:
@Component({
selector: 'app-status',
template: `<p>User is logged in: {{ loggedIn }}</p>`
})
export class StatusComponent {
loggedIn = false;
constructor(private auth: AuthService) {
this.auth.isLoggedIn$.subscribe(status => {
this.loggedIn = status;
});
}
}
✨ The best part? No matter when the component is created, it will always get the current login state.
📊 Quick Comparison
Feature | Subject | BehaviorSubject |
---|---|---|
Initial value needed | ❌ No | ✅ Yes |
Remembers last value | ❌ No | ✅ Yes |
Late subscribers get value | ❌ No | ✅ Yes |
Best for | Event streams | Shared state / app status |
💡 Final Thoughts
RxJS can feel overwhelming at first, but once you understand the strengths of Subject
and BehaviorSubject
, you’ll reach for them instinctively.
Here’s my go-to rule:
- Use
Subject
for things that happen in the moment (clicks, triggers). - Use
BehaviorSubject
when the latest state matters (auth, settings, theme, etc).
Start with the one that matches your use case, and you’ll avoid over-complicating things.