Skip to content

perf(cache): short TTL for gallery image listings#513

Merged
Zheaoli merged 1 commit into
mainfrom
be-image-list-short-ttl
May 31, 2026
Merged

perf(cache): short TTL for gallery image listings#513
Zheaoli merged 1 commit into
mainfrom
be-image-list-short-ttl

Conversation

@Zheaoli
Copy link
Copy Markdown
Collaborator

@Zheaoli Zheaoli commented May 31, 2026

Background

The public gallery image-list caches (the gallery tag in server/lib/cache.ts) are the only cached reads whose freshness depends on a background source. The preprocess ticker flips variants_ready outside request scope, so it cannot call revalidateTag — Next throws Invariant: static generation store missing when there is no work store. As a result, that update was only picked up when the 1h safety-net TTL expired, so a freshly-processed image could keep showing its placeholder for up to an hour after its variants were actually ready.

Change

Give the four gallery-tagged wrappers their own 60s TTL, while leaving the albums and config caches at 1h.

  • albums / config only change via admin writes, which bust their tags synchronously in request scope — so a long safety-net TTL remains fine for them.
  • Admin writes still invalidate the gallery tag instantly via revalidateGalleryCache (image create / update / delete / show-hide / sort). The short TTL only bounds the background-ticker gap, now ≤60s instead of ≤1h.
  • A 60s window still absorbs the bulk of repeat reads, so page-1 first paint stays a cache hit for most requests (it is hit during server render via the FU-15 preload hint).

Why option ① (short TTL) over the alternatives

  • Uncaching the image-list would also work, but it is not TTFB-free: the server-side preload hint calls getImagesData(1, album) during page render, so the image-list cache helps first paint — dropping it adds a DB query there.
  • A request-scoped revalidate route fetched by the ticker would make updates instant but adds a route plus internal auth — heavier than warranted for a ≤60s bound.

Short TTL is one line per wrapper, keeps the page-1 first-paint cache hit, and bounds staleness to ≤60s.

Scope / risk

  • Single file, comment + one new constant applied to four wrappers. No behavior change for albums/config, no change to the auth/render model.
  • No new TypeScript errors introduced in the touched file.

The public gallery image-list caches (`gallery` tag) are the only cached
reads whose freshness depends on a background source: the preprocess
ticker flips `variants_ready` outside request scope and therefore cannot
call `revalidateTag` (Next throws "Invariant: static generation store
missing" with no work store). Those updates were only picked up when the
1h safety-net TTL expired, so a freshly-processed image could keep
showing its placeholder for up to an hour after its variants were ready.

Give the four `gallery`-tagged wrappers their own 60s TTL while leaving
albums/config at 1h. Albums and config only change via admin writes that
bust their tags synchronously in request scope, so they keep the long
safety-net TTL. Admin writes still invalidate the gallery tag instantly
via `revalidateGalleryCache`; the short TTL only bounds the
background-ticker gap (now <=60s) and still absorbs the bulk of repeat
reads, so page-1 first paint stays a cache hit for most requests.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
picimpact Ready Ready Preview, Comment May 31, 2026 7:42pm

@Zheaoli Zheaoli merged commit 90769b2 into main May 31, 2026
6 checks passed
@Zheaoli Zheaoli deleted the be-image-list-short-ttl branch May 31, 2026 19:45
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