Skip to content

Why Do Images Load Slowly and Inconsistently? Possible Vercel Edge Cache Issues #16299

@cfmcfmcfm

Description

@cfmcfmcfm

Description

We're noticing that image load times are inconsistent and sometimes very slow. When requesting the same optimized image multiple times, we observe unusual cache behavior: the age header values sometimes jump backward, cache misses occur without obvious reason, and load times vary significantly (200ms → 2500ms). This happens repeatedly across multiple requests to identical URLs within seconds, and incognito windows seem to show different cache states than regular browsing. Is this expected behavior, or is something going wrong with how the edge cache is handling these requests?

Expected Behavior

  • Once an image is cached, all requests should consistently return x-vercel-cache: HIT
  • The age value should increase steadily with a predictable progression
  • Load times should remain consistently fast (~150-200ms for cached assets)

Actual Behavior

  • Cache hits and misses occur unpredictably for identical requests to the same image
  • age values jump backward (e.g., 10160 → 2340), reset to 0, then jump forward again (→ 11200)
  • Load times vary dramatically: cached hits load in ~150-200ms, misses take 2000-2500ms (10x slower)
  • Each cache miss forces image re-optimization, further impacting performance
  • Incognito windows receive different age values and cache states than regular browsing, even for the same URL

Example - Cache Age Jumping Backward and Misses

Request 1: age: 10160, load time: 200ms,  x-vercel-cache: HIT    (cached for 10160 seconds)
Request 2: age: 2340,  load time: 150ms,  x-vercel-cache: HIT    (age went backward?!)
Request 3: age: 0,     load time: 2500ms, x-vercel-cache: MISS    (cache miss, had to re-optimize)
Request 4: age: 45,    load time: 200ms,  x-vercel-cache: HIT    (age stays low)
Request 5: age: 11200, load time: 180ms,  x-vercel-cache: HIT    (age jumped forward again)

This pattern seems to repeat, but inconsistently. Sometimes we see multiple misses in a row, sometimes mostly hits. The age values don't follow a clear progression—they jump backward, reset to 0, then jump forward. The incognito window shows different age values for the same URL, which is puzzling—is this expected?

Link to the code that reproduces this issue

https://github.com/leandesigngmbh/payload-website-starter-img-caching

Reproduction Steps

  1. Navigate to any page with Next.js Image component optimized images (https://payload-website-starter-img-caching.vercel.app/test)
  2. Open browser DevTools → Network tab, filter by the image request
  3. Reload page multiple times over 30-60 seconds and note the age and cache headers
  4. The unusual behavior may not appear immediately—sometimes multiple reloads show consistent HIT, then suddenly ages jump or misses occur
  5. Try reloading again after 2-5 minutes—the pattern often becomes visible with this timing
  6. Open the same page in incognito window and compare the age values
  7. Switch back to regular window and reload again—cache state may have changed

Performance Impact

  • Images often take longer to load than expected
  • Load times seem to vary inconsistently between requests to the same asset
  • There may be a correlation with cache misses and age value inconsistencies—is there a connection?

Additional Context

This seems to be impacting performance:

  • Cache hits vary: Images don't seem to stay cached reliably
  • Load times differ: Same image loads in 150ms sometimes, 2500ms other times (17x difference)
  • Possible extra costs: Cache misses might force unnecessary image re-optimization
  • User experience: Pages feel slow and unpredictable—is the CDN cache working as expected?

Possible causes

  1. Is the edge cache being differently handled between PoPs/regions?
  2. Could cache eviction be happening more aggressively than expected?
  3. Are identical URLs being routed to different cache entries?
  4. Could there be an issue with how cache headers or time-based keys (like updatedAt timestamps) are being processed?

Which area(s) are affected?

plugin: storage-*

Environment Info

Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: 1.22.22
  pnpm: 10.33.0
Relevant Packages:
  payload: 3.82.1
  next: 16.2.3
  @payloadcms/db-vercel-postgres: 3.82.1
  @payloadcms/drizzle: 3.82.1
  @payloadcms/graphql: 3.82.1
  @payloadcms/live-preview: 3.82.1
  @payloadcms/live-preview-react: 3.82.1
  @payloadcms/next/utilities: 3.82.1
  @payloadcms/plugin-cloud-storage: 3.82.1
  @payloadcms/plugin-form-builder: 3.82.1
  @payloadcms/plugin-nested-docs: 3.82.1
  @payloadcms/plugin-redirects: 3.82.1
  @payloadcms/plugin-search: 3.82.1
  @payloadcms/plugin-seo: 3.82.1
  @payloadcms/richtext-lexical: 3.82.1
  @payloadcms/storage-vercel-blob: 3.82.1
  @payloadcms/translations: 3.82.1
  @payloadcms/ui/shared: 3.82.1
  react: 19.2.4
  react-dom: 19.2.4
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.6.0: Mon Jan 19 21:58:37 PST 2026; root:xnu-11417.140.69.708.3~1/RELEASE_ARM64_T8103
  Available memory (MB): 16384
  Available CPU cores: 8

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions