Question
Subject vs BehaviorSubject in RxJS: What’s the Difference?
Question
In RxJS, what is the difference between Subject and BehaviorSubject?
I am not sure whether the only difference is that BehaviorSubject provides a getValue() method, or whether there are important behavioral differences in how they emit values to subscribers.
Short Answer
By the end of this page, you will understand the core difference between Subject and BehaviorSubject in RxJS: a BehaviorSubject stores the latest value and immediately gives it to new subscribers, while a Subject only emits values that happen after subscription. You will also see when to use each one, common mistakes, and how this choice appears in real codebases.
Concept
Subject and BehaviorSubject are both special RxJS types that are observables and observers at the same time.
That means they can:
- emit values using
next() - be subscribed to like any observable
The important difference is how they treat the current value.
Subject
A Subject does not keep a stored current value for new subscribers.
- If a value was emitted before you subscribed, you will not receive it.
- You only receive values emitted after your subscription starts.
BehaviorSubject
A BehaviorSubject always has a current value.
- It must be created with an initial value.
- When a new subscriber subscribes, it immediately receives the latest stored value.
- After that, it continues receiving future emissions.
Why this matters
This difference is important whenever your app needs to answer the question:
"What is the current state right now?"
Mental Model
Think of a Subject like a live radio broadcast.
- If you tune in late, you only hear what is broadcast from that moment onward.
- You miss everything that was already said.
A BehaviorSubject is like a radio station that first tells you the current status before continuing live.
- When you join, it immediately tells you the latest update.
- Then it keeps giving you new live updates.
Another analogy:
Subject= a doorbell: you only hear rings that happen while you are there.BehaviorSubject= a thermostat display: you can always see the current temperature immediately, then notice future changes.
Syntax and Examples
Basic syntax
import { Subject, BehaviorSubject } from 'rxjs';
const subject = new Subject();
const behaviorSubject = new BehaviorSubject('initial value');
Example: Subject
import { Subject } from 'rxjs';
const subject = new Subject();
subject.next('A');
subject.subscribe(value => {
console.log('Subscriber 1:', value);
});
subject.next('B');
subject.next('C');
Output:
Subscriber 1: B
: C
Step by Step Execution
Consider this example:
import { BehaviorSubject } from 'rxjs';
const status$ = new BehaviorSubject('offline');
status$.next('connecting');
status$.subscribe(value => {
console.log('Subscriber A:', value);
});
status$.next('online');
Here is what happens step by step:
-
const status$ = new BehaviorSubject('offline');- A
BehaviorSubjectis created. - Its current value is
'offline'.
- A
-
status$.next('connecting');- The current value changes from
'offline'to'connecting'. - There are no subscribers yet, so nothing is logged.
- The current value changes from
-
status$.subscribe(...)
Real World Use Cases
When to use Subject
Use Subject for events that do not need a remembered current value.
Examples:
- button click event streams
- refresh notifications
- modal open/close triggers
- "user submitted the form" events
- internal app events between services
const refresh$ = new Subject();
refresh$.subscribe(() => {
console.log('Reload data');
});
refresh$.next();
Here, you usually care about the event happening now, not the last event from earlier.
When to use BehaviorSubject
Use BehaviorSubject for state that should always have a current value.
Examples:
- current user
- current selected language
- loading status
- current page number
- current filter settings
const loading$ = new BehaviorSubject();
loading$.( {
.(, value);
});
loading$.();
loading$.();
Real Codebase Usage
In real projects, developers often choose between these two based on whether they are modeling an event stream or a state container.
Common BehaviorSubject pattern: service state
import { BehaviorSubject } from 'rxjs';
class AuthService {
constructor() {
this.userSubject = new BehaviorSubject(null);
this.user$ = this.userSubject.asObservable();
}
login(user) {
this.userSubject.next(user);
}
logout() {
this.userSubject.next(null);
}
}
Why this is common:
nullacts as the initial state- components can subscribe at any time
- new subscribers immediately get the latest user state
Common Mistakes
1. Thinking BehaviorSubject is only Subject plus getValue()
This is the main misunderstanding.
The biggest difference is immediate replay of the latest value to new subscribers.
2. Forgetting that BehaviorSubject needs an initial value
This is required:
const count$ = new BehaviorSubject(0);
This is invalid:
const count$ = new BehaviorSubject();
Always choose an initial value that makes sense, such as:
0falsenull[]{}
3. Using Subject when you really need current state
Broken idea:
Comparisons
| Feature | Subject | BehaviorSubject |
|---|---|---|
| Requires initial value | No | Yes |
| Stores current value | No | Yes |
| New subscriber gets latest value immediately | No | Yes |
| Good for event streams | Yes | Sometimes |
| Good for state | Usually no | Yes |
Has getValue() | No | Yes |
Subject vs BehaviorSubject in one sentence
Subjectis for .
Cheat Sheet
Quick reference
Subject
const subject = new Subject();
subject.next(value);
subject.subscribe(value => console.log(value));
- no initial value required
- does not store the latest value
- new subscribers only get future emissions
- best for events
BehaviorSubject
const state$ = new BehaviorSubject(initialValue);
state$.next(newValue);
state$.subscribe(value => console.log(value));
const current = state$.getValue();
- requires an initial value
- stores the latest value
- new subscribers immediately receive the current value
- best for state
Rules of thumb
- event stream ->
Subject
FAQ
Is BehaviorSubject just Subject with getValue()?
No. The main difference is that BehaviorSubject stores the latest value and immediately sends it to new subscribers.
Why does BehaviorSubject need an initial value?
Because it always represents a current value. RxJS needs to know what that current value is from the start.
When should I use Subject instead of BehaviorSubject?
Use Subject for one-time or ongoing events where you do not need to remember the current state, such as clicks, refresh triggers, or notifications.
When should I use BehaviorSubject?
Use it when your app needs a current state that new subscribers should receive immediately, such as the current user, loading status, or selected item.
Do late subscribers miss values with Subject?
Yes. A Subject does not replay old values. Late subscribers only receive future emissions.
Do late subscribers miss values with BehaviorSubject?
They may miss older history, but they will always receive the latest current value immediately.
Mini Project
Description
Build a small reactive status store for an application. This project demonstrates why BehaviorSubject is useful for storing current state and why Subject is useful for fire-and-forget events. You will model a user's online status as state and a refresh action as an event.
Goal
Create a simple RxJS example where new subscribers instantly receive the current status from a BehaviorSubject, while refresh events are handled through a Subject.
Requirements
- Create a
BehaviorSubjectto store the user's current status - Create a
Subjectto represent refresh button clicks - Add at least one subscriber before updating values and one subscriber after updating values
- Show in the output that late subscribers receive the latest status but do not receive old refresh events
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular @ViewChild Returning Undefined: Lifecycle, Child Components, and Fixes
Learn why Angular @ViewChild can be undefined, when it becomes available, and how to access child components correctly using lifecycle hooks.