shareReplay can be the perfect Angular HTTP cache or the source of stale data and retained subscriptions. The real question is not just what it replays, but when the shared subscription resets and whether the cached value should outlive the current consumers.
Use this Angular interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
What Is shareReplay in RxJS and How Can It Silently Break Your Angular App?Frontend interview answer
This Angular interview question tests whether you can explain RxJS shareReplay in Angular: HTTP caching, stale data, and refCount traps, connect it to production trade-offs, and handle common follow-up questions.
- RxJS shareReplay in Angular: HTTP caching, stale data, and refCount traps explanation without falling back to memorized docs wording
- RxJS and Sharereplay reasoning, edge cases, and production failure modes
- How you would answer the most likely Angular interview follow-up
Cache-and-share operatorshareReplay does two things at once: it shares one subscription across subscribers and it replays the last emitted values to late subscribers. That is perfect for caching a cold HTTP request, but dangerous for long-lived streams when stale cached values or never-reset subscriptions stick around longer than you expected.
Worked examplethis.user$ = this.http.get('/api/me').pipe(shareReplay({ bufferSize: 1, refCount: true })) can prevent duplicate HTTP calls when multiple components subscribe. The bug appears when teams apply the same pattern to long-lived service streams without thinking about reset behavior: old values keep replaying, subscribers never fully disappear, or the cache survives longer than the data should.
Rule of thumb
- Cold HTTP caching is the safe default use case.
- Long-lived app-state streams need explicit thinking about
refCount, reset behavior, and stale data. - If you cannot explain when the cached value disappears, you have not finished the operator design.
The classic Angular use-case
You want multiple components to consume the same HTTP data without triggering multiple requests.
users$ = this.http.get<User[]>('/api/users').pipe(
shareReplay(1)
);
What problem does this solve?
Without shareReplay, every subscribe() or async pipe would trigger a new HTTP request. With shareReplay(1), the first request is cached and reused.
Behavior | Without shareReplay | With shareReplay(1) |
|---|---|---|
Second subscriber | Triggers new HTTP request | Gets cached value |
Third subscriber | Triggers new HTTP request | Gets cached value |
Network usage | Many duplicate calls | Single call |
How shareReplay can silently break your app
Problem | Why it happens | Symptom in real apps |
|---|---|---|
Memory leaks | By default, shareReplay keeps the source subscribed forever. | Services never released, WebSocket connections and intervals never stop. |
Stale data | Cached value is reused even when data should refresh. | User navigates away/back and sees outdated data. |
Error caching | If the source errors, the error is also replayed. | Stream is permanently broken until reload. |
Unexpected global state | shareReplay turns cold streams into hot singletons. | Components influence each other indirectly. |
The most important option: refCount
Modern RxJS lets you write:
users$ = this.http.get<User[]>('/api/users').pipe(
shareReplay({ bufferSize: 1, refCount: true })
);
What does refCount: true do?
It tells RxJS: “When there are no subscribers left, unsubscribe from the source and free resources.” Without this, the source stays alive forever.
Configuration | When last subscriber unsubscribes | Memory behavior |
|---|---|---|
shareReplay(1) | Source stays subscribed | ❌ Potential leak |
shareReplay({ bufferSize: 1, refCount: true }) | Source unsubscribes | ✅ Safe cleanup |
Another subtle trap: error caching
If the HTTP call errors once, shareReplay will replay that error forever. All future subscribers instantly get the error, and the stream never retries unless you rebuild it or add retry logic.
users$ = this.http.get<User[]>('/api/users').pipe(
retry(1),
shareReplay({ bufferSize: 1, refCount: true })
);
Senior rule of thumb
• Use shareReplay for caching expensive or shared streams.
• Prefer { bufferSize: 1, refCount: true } unless you intentionally want a forever-alive cache.
• Be explicit about refresh/invalidation semantics.
• Never blindly slap shareReplay(1) everywhere.
Angular scenario | Should you use shareReplay? | How |
|---|---|---|
Config loaded once at app startup | ✅ Yes | shareReplay(1) without refCount may be OK |
User-specific API data | ⚠️ Be careful | Use refCount or explicit refresh trigger |
WebSocket / interval stream | ❌ Usually dangerous | You probably want manual lifecycle control |
HTTP list used by many components | ✅ Yes | shareReplay({ bufferSize: 1, refCount: true }) |
Interview summaryshareReplay shares a single subscription and caches the last values. It is great for avoiding duplicate HTTP calls, but can cause memory leaks, stale data, and permanent error states if used carelessly. In Angular, the safe default is shareReplay({ bufferSize: 1, refCount: true }) and a clear cache invalidation strategy.
Use this as one explanation rep, then continue with the Angular interview questions cluster or a guided prep path.