← All journals

Image Performance Before and After Adding CloudFront

Tracing an S3 image request through the browser, Next.js image optimization, and CloudFront caching.

  • Next.js
  • AWS
  • CloudFront
  • Web Optimization

Summary

Our team introduced AWS CloudFront to improve product-image delivery in Snack, a Next.js application deployed on Vercel.

The /products page loads many images stored in Amazon S3, making it an ideal page for comparing performance before and after implementing CloudFront.

I tested both versions in production using Lighthouse’s mobile and desktop presets. The results showed faster Speed Index scores and higher overall performance scores, although LCP did not improve consistently.

One limitation: Vercel’s Next.js Image Optimization has its own image cache. Later Lighthouse runs may load images from Vercel without reaching CloudFront. Because of this, the results show how the full production setup performed after adding CloudFront, rather than what CloudFront improved on its own.

Implementation Result

Lighthouse results before and after introducing CloudFront
MetricBeforeAfterChange
Mobile LCP7.5s7.7s+0.2s
Mobile CLS00—
Mobile Speed Index2.4s1.7s−0.7s
Mobile Performance7175+4
Desktop LCP1.8s1.6s−0.2s
Desktop CLS00—
Desktop Speed Index1.2s0.5s−0.7s
Desktop Performance9295+3
View test method
  • Environment: Production /products page deployed on Vercel.
  • Comparison: Product image sources changed from direct S3 URLs to CloudFront URLs.
  • Browser: Chrome Incognito with browser caching disabled in DevTools.
  • Mobile: Lighthouse mobile preset with its default simulated Slow 4G network and CPU throttling.
  • Desktop: Lighthouse desktop preset with its default throttling settings.
  • Controlled variables: The same page, images, production environment, and Lighthouse settings were used for both versions.
  • Runs: Five runs for each mobile and desktop test, with the median reported above.
  • Scope: The complete production pipeline, including Vercel’s Next.js Image Optimization cache, was measured rather than CloudFront alone.

Result Analysis

The clearest improvement was in Speed Index. Mobile Speed Index improved by 0.7 seconds, while desktop Speed Index also improved by 0.7 seconds. The overall performance score increased by four points on mobile and three points on desktop.

LCP did not improve consistently. Desktop LCP improved by 0.2 seconds, while mobile LCP became 0.2 seconds slower. This suggests that the updated pipeline helped display page content sooner overall but did not resolve the mobile LCP bottleneck. I plan to investigate that issue separately.

How the Image Request Flows

Vercel first checks its optimized-image cache and only contacts CloudFront when it needs the source image. CloudFront then checks its cache hierarchy before contacting S3.

Full miss
CloudFront hit
Vercel hit
Browser hit

Browser

Checks its own cache first

Vercel / Next.js Image Optimization

Checks its optimized-image cache, then requests the source when needed

CloudFront

Checks its edge and regional caches for the source image

S3 (Oregon)

Origin, only reached on a full miss

The request stops as soon as a layer has a valid cached response. CloudFront is only contacted when Vercel needs the source image.

Limits

  • CloudFront was not measured in isolation. Vercel’s Next.js Image Optimization also caches optimized images. After the first request, later Lighthouse runs may receive a Vercel cache hit without contacting CloudFront. The request-flow diagram shows where a Vercel hit stops the request.
  • CloudFront does not fix late LCP discovery. It can reduce the time needed to retrieve an image after it is requested, but it cannot make the browser discover the LCP image earlier. I plan to investigate that issue separately.
  • Lighthouse results naturally vary. Network conditions, service load, and background activity can affect individual runs even with simulated throttling. Reporting the median of five runs reduces the effect of outliers but does not remove all variation.