The problem
On every poll, Gitify re-fetches data it already has:
- Re-enriches every notification, even unchanged ones. For N visible notifications,
getAllNotifications → enrichNotifications (src/renderer/utils/notifications/notifications.ts) issues ceil(N / 100) GraphQL detail queries every interval, with no change detection (enrich.ts, GITHUB_API_MERGE_BATCH_SIZE = 100).
- Disables caching on the list request.
listNotificationsForAuthenticatedUser (client.ts) sets Cache-Control: no-cache, so the full notifications list is re-downloaded every poll even when nothing changed.
For someone watching busy repos, nearly every request each minute is redundant.
Why fixing it helps
GitHub's API makes the "nothing changed" case almost free — Gitify just isn't using the mechanisms:
- Conditional requests (
If-Modified-Since / If-None-Match) return 304 Not Modified with an empty body, and 304s don't count against the rate limit.
X-Poll-Interval tells clients the minimum safe poll spacing.
Adopting these turns the common steady-state poll from "re-download the whole list + re-fetch every notification" into "one conditional request that returns 304, zero detail fetches." Result: much lower API/
rate-limit usage and bandwidth, fewer throttled requests, and no change to user-visible behavior. This especially helps heavy users and anyone running multiple accounts.
Proposed fixes (independent, in priority order)
- Skip re-enriching unchanged notifications. Cache the enriched subject keyed by account + id +
updatedAt; reuse it when updatedAt is unchanged, only fetching cache misses. Prune to current
notifications each cycle. Forge-agnostic — lives in the enrichment orchestrator.
- Conditional requests on the list. Drop
Cache-Control: no-cache, send If-Modified-Since/If-None-Match, store the returned Last-Modified/ETag per account, and reuse the last list on 304. Localized to client.ts.
- Respect
X-Poll-Interval. Poll no more often than max(userInterval, X-Poll-Interval) (useNotifications.ts currently uses only the fixed fetchIntervalMs).
References
Happy to open a PR for these.
The problem
On every poll, Gitify re-fetches data it already has:
getAllNotifications→enrichNotifications(src/renderer/utils/notifications/notifications.ts) issuesceil(N / 100)GraphQL detail queries every interval, with no change detection (enrich.ts,GITHUB_API_MERGE_BATCH_SIZE = 100).listNotificationsForAuthenticatedUser(client.ts) setsCache-Control: no-cache, so the full notifications list is re-downloaded every poll even when nothing changed.For someone watching busy repos, nearly every request each minute is redundant.
Why fixing it helps
GitHub's API makes the "nothing changed" case almost free — Gitify just isn't using the mechanisms:
If-Modified-Since/If-None-Match) return304 Not Modifiedwith an empty body, and304s don't count against the rate limit.X-Poll-Intervaltells clients the minimum safe poll spacing.Adopting these turns the common steady-state poll from "re-download the whole list + re-fetch every notification" into "one conditional request that returns
304, zero detail fetches." Result: much lower API/rate-limit usage and bandwidth, fewer throttled requests, and no change to user-visible behavior. This especially helps heavy users and anyone running multiple accounts.
Proposed fixes (independent, in priority order)
updatedAt; reuse it whenupdatedAtis unchanged, only fetching cache misses. Prune to currentnotifications each cycle. Forge-agnostic — lives in the enrichment orchestrator.
Cache-Control: no-cache, sendIf-Modified-Since/If-None-Match, store the returnedLast-Modified/ETagper account, and reuse the last list on304. Localized toclient.ts.X-Poll-Interval. Poll no more often thanmax(userInterval, X-Poll-Interval)(useNotifications.tscurrently uses only the fixedfetchIntervalMs).References
Happy to open a PR for these.