ETag/Last-Modified Conditional Request Support for Polling Mode
Track: etag-polling-20260329
Overview
Add HTTP conditional request support (ETag, Last-Modified, 304 Not Modified) to the polling mode using make-fetch-happen as the fetch layer. This reduces API rate limit consumption by avoiding redundant data transfers when tracker data hasn't changed between poll cycles.
For GitHub, a hybrid approach is used: a lightweight REST GET with ETag checks whether project items have changed — if 304 (unchanged), skip the full GraphQL query and return cached results; if 200 (changed), run the existing GraphQL query to fetch complete data including fields only available via GraphQL (reviewDecision, headRefName, closedByPullRequestsReferences). GitHub's GraphQL API uses POST requests which do not support HTTP caching.
For Asana, make-fetch-happen replaces the plain fetch() calls, providing automatic ETag/Last-Modified caching on all GET requests.
Requirements
Functional Requirements
Non-functional Requirements
Acceptance Criteria
Out of Scope
- Webhook mode changes — only polling mode gets caching
- Asana webhook support — Asana caching is REST-only
- Dashboard cache stats UI — no visualization of cache metrics in this track
- Full GitHub GraphQL-to-REST migration — GraphQL remains the primary data source; REST is only used for change detection
- GitHub GraphQL response caching — POST requests are not cacheable via HTTP
Assumptions
ETag/Last-Modified Conditional Request Support for Polling Mode
Overview
Add HTTP conditional request support (ETag, Last-Modified, 304 Not Modified) to the polling mode using
make-fetch-happenas the fetch layer. This reduces API rate limit consumption by avoiding redundant data transfers when tracker data hasn't changed between poll cycles.For GitHub, a hybrid approach is used: a lightweight REST GET with ETag checks whether project items have changed — if 304 (unchanged), skip the full GraphQL query and return cached results; if 200 (changed), run the existing GraphQL query to fetch complete data including fields only available via GraphQL (
reviewDecision,headRefName,closedByPullRequestsReferences). GitHub's GraphQL API uses POST requests which do not support HTTP caching.For Asana,
make-fetch-happenreplaces the plainfetch()calls, providing automatic ETag/Last-Modified caching on all GET requests.Requirements
Functional Requirements
make-fetch-happenas the cached fetch implementation for REST API callscachePath) for HTTP response cachingfetchIssueStatesByIds) and status updates (updateItemStatus) — unchangedmake-fetch-happenkey=valuelogs via consola)Non-functional Requirements
{workspace.root}/.cache/http)Acceptance Criteria
make-fetch-happenis used for all REST HTTP calls (GitHub REST check, Asana API)Out of Scope
Assumptions