get-convex / get-convex/convex-react-query
Decouple subscription lifetime from cache retention (stale-while-revalidate)
- Dominant language
- TypeScript
- Stars
- 41
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
If I understand the implementation correctly, `gcTime` currently controls both how long the Convex WebSocket subscription stays alive **and** how long cached data is retained after unmount. When `gcTime` expires, the `"removed"` event fires, `unsubscribe()` is called, and the data is evicted from TanStack Query's cache simultaneously.
This means there doesn't seem to be a way to get a stale-while-revalidate pattern:
- **Short `gcTime`** = saves bandwidth but loses cached data → loading flash on remount
- **Long `gcTime`** = instant remount but keeps subscription open → unnecessary bandwidth for unmounted components
## Proposed behavior
Use `staleTime` and `gcTime` with their natural TanStack Query semantics:
| Setting | Current behavior | Proposed behavior |
|---|---|---|
| `staleTime` | Set to `Infinity` (data is never stale while subscribed) | Controls how long the **subscription** stays alive after all observers unmount. While subscribed = fresh. |
| `gcTime` | Controls both subscription **and** cache lifetime | Controls how long **stale cached data** is retained after the subscription is dropped |
### Example
```ts
convexQuery(api.messages.list, { channel: "general" }, {
staleTime: 10_000, // drop subscription 10s after unmount
gcTime: 5 * 60_000, // keep last-known data in cache for 5 min
})
```
### Remount behavior
1. **0–10s after unmount**: subscription alive, data fresh, instant remount
2. **10s–5min after unmount**: subscription dropped (no bandwidth cost), stale data shown instantly on remount, new subscription opened in background, UI updates when first message arrives
3. **After 5min**: cache evicted, remount = loading state + new subscription
## Why this matters
Convex subscriptions have a real bandwidth cost — the server keeps pushing updates over WebSocket even when no component is consuming the data. For apps with many routes/views, keeping subscriptions alive for 5 minutes after navigating away adds up.
The stale-while-revalidate pattern would be the sweet spot: no bandwidth waste while unmounted, but no loading flash on remount either.
## Possible implementation sketch
1. On observer count dropping to 0, start a `staleTime` timer (instead of relying solely on TanStack's `gcTime`-based `"removed"` event)
2. When `staleTime` timer fires, call `unsubscribe()` but **leave the data in TanStack's cache** (mark as stale)
3. On re-observe (component remounts), TanStack sees stale data → shows it immediately → adapter re-subscribes → pushes fresh data into cache when first update arrives
4. `gcTime` continues to control when the cache entry itself is evicted
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.