shareReplay({ refCount }) after upgrading to RxJS 7: old buffered values still replayed to new subscribers
26.5K reputation · 15 Jun 2025, 08:00 UTC
shareReplay caching behavior across the RxJS 6 to 7 boundary
We cache an HTTP response with shareReplay so multiple components share one request. After upgrading from RxJS 6 to 7, we want to move from the legacy shareReplay(1) form to the documented configuration object shareReplay({ bufferSize: 1, refCount: true }), mainly so the source subscription is torn down when the last subscriber leaves.
The uncertainty is about what happens to the buffer itself. My understanding is that refCount: true unsubscribes from the source at zero subscribers, but the internal ReplaySubject buffer may not be cleared, so a subscriber arriving later could still receive the previously buffered (now stale) value before any fresh emission. I also understand that once the source errors, the ReplaySubject is terminated and later subscribers receive the cached error rather than triggering a new subscription.
RxJS 7 reworked share() with a configuration object and aligned shareReplay with it, so the reset semantics may differ from what we relied on in 6.x.
- With
refCount: true, is the buffer guaranteed to persist after teardown, or does RxJS 7 reset it? - Is there a documented way to get reset-on-error and reset-on-refCount behavior via
share()config instead? - Do these semantics differ between 6.x and 7.x in a way that affects migration?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 15 Jun 2025, 14:52 UTC
To clarify the internal mechanism in RxJS 7: refCount: true manages the subscription to the source, but it does not automatically purge the internal buffer when the subscriber count hits zero.
When a new subscriber arrives after a teardown, the operator re-subscribes to the source, but it immediately emits the values remaining in the ReplaySubject buffer first. This explains why a new subscriber receives stale data before the fresh request is triggered. To ensure a completely clean state upon resubscription, shareReplay may not be the right tool, as its primary purpose is to maintain that buffer across subscription cycles.
Verification Tip
You can verify this behavior by using a timer source with shareReplay({ bufferSize: 1, refCount: true }). Subscribe and unsubscribe, wait for the timer to advance, and then re-subscribe; you will see the last emitted value from the previous session delivered immediately before the new timer tick.