Skip to content

fix(api): Cache-Control + Vary on /api/v1/usage/wall#190

Merged
mastermanas805 merged 2 commits into
masterfrom
fix/api-usage-wall-cache-control-2026-05-30
May 30, 2026
Merged

fix(api): Cache-Control + Vary on /api/v1/usage/wall#190
mastermanas805 merged 2 commits into
masterfrom
fix/api-usage-wall-cache-control-2026-05-30

Conversation

@mastermanas805

Copy link
Copy Markdown
Member

Summary

  • BUG-API-420: dashboard fetches /api/v1/usage/wall on every nav + 5-min poll; without a cache hint the browser re-fetches on every back/forward / SPA route change, generating redundant DB scans on the busy team-scoped audit_log table.
  • Stamp Cache-Control: private, max-age=30 + Vary: Authorization on every 200 path.

Consistency tradeoff (memory rule feedback_caching_and_consistency_tradeoffs)

  • Worker writes ≤1 near_quota_wall row per team per 24h (quotaWallDedupeWindow). 30s staleness window can miss a brand-new wall event by ≤30s — fine for a soft upgrade nudge.
  • Hard 402 quota enforcement still fires synchronously on the next provision regardless of cached banner state.
  • 30s << the 5-min dashboard poll interval, so walls become visible within 5min + 30s in the worst case.
  • Vary: Authorization keys per-team caching to the bearer token so a shared CDN / browser back-cache after re-auth never serves team A's banner to team B.

Coverage block (rule 17)

Symptom:       /api/v1/usage/wall returns no Cache-Control hint
Enumeration:   GetWall has THREE distinct 200 code paths
               (team-tier short-circuit, no-recent-row,
               row-found-with-metadata).
Sites found:   3
Sites touched: 3 — one setUsageWallCacheHeaders call on each
Coverage test: TestUsageWall_CacheHeadersOnEvery200Path iterates
               the registry of 3 paths via a test table and asserts
               the same Cache-Control + Vary on every one — adding
               a 4th 200 path without the cache header fails the
               test (rule 18 registry-iterating pattern).
Live verified: pending CI auto-deploy (rule 14 SHA check after merge).

Test plan

  • go build ./... clean
  • go vet ./... clean
  • go test ./internal/handlers -run TestUsageWall all pass
  • setUsageWallCacheHeaders: 100% covered
  • GetWall: 96.3% (uncovered: pre-existing db_failed branch outside diff)
  • Live verify after merge: curl -i -H "Authorization: Bearer <pat>" https://api.instanode.dev/api/v1/usage/wall | grep -i 'cache-control\|^vary'

Inbox: BUG-API-420

@mastermanas805 mastermanas805 force-pushed the fix/api-usage-wall-cache-control-2026-05-30 branch from be165df to f54224d Compare May 30, 2026 07:28
mastermanas805 and others added 2 commits May 30, 2026 13:15
BUG-API-420: the dashboard fetches /api/v1/usage/wall on every nav
(Overview mount + 5-min poll); without a cache hint the browser
re-fetches on every back/forward / SPA route change, generating
redundant scans on the busy team-scoped audit_log table.

Stamp `Cache-Control: private, max-age=30` + `Vary: Authorization`
on every 200 path. Consistency tradeoff (memory rule
feedback_caching_and_consistency_tradeoffs):

- worker writes ≤1 near_quota_wall row per team per 24h
  (quotaWallDedupeWindow), so 30s staleness window can miss a
  brand-new wall event by ≤30s — irrelevant for a soft upgrade
  nudge.
- hard 402 quota enforcement still fires synchronously on the
  next provision regardless of cached banner state.
- 30s << the 5-min dashboard poll interval, so walls become
  visible within 5min + 30s in the worst case.
- Vary: Authorization keys per-team caching to the bearer token
  so a shared CDN / browser back-cache after re-auth never
  serves team A's banner to team B.

Coverage block (rule 17):
Symptom:       /api/v1/usage/wall returns no Cache-Control hint
Enumeration:   GetWall has THREE distinct 200 code paths
               (team-tier short-circuit, no-recent-row,
               row-found-with-metadata).
Sites found:   3
Sites touched: 3 — one setUsageWallCacheHeaders call on each
Coverage test: TestUsageWall_CacheHeadersOnEvery200Path iterates
               the registry of 3 paths via a test table and asserts
               the same Cache-Control + Vary on every one — adding
               a 4th 200 path without the cache header fails the
               test (rule 18 registry-iterating pattern).
Live verified: pending CI auto-deploy (rule 14 SHA check after merge).

setUsageWallCacheHeaders: 100% covered.
GetWall: 96.3% (uncovered: pre-existing db_failed branch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eHeaders

golangci-lint flagged the constant as unused — it was kept as a
single-source-of-truth comment but never read. Wire it through
fmt.Sprintf so the wire value and the comment are coupled: anyone
deleting the constant must also touch the format string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 force-pushed the fix/api-usage-wall-cache-control-2026-05-30 branch from f54224d to 013b0b6 Compare May 30, 2026 07:45
@mastermanas805 mastermanas805 merged commit 063d0fd into master May 30, 2026
14 checks passed
@mastermanas805 mastermanas805 deleted the fix/api-usage-wall-cache-control-2026-05-30 branch May 30, 2026 08:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant