Skip to main content
友田 陽大
Vercel in production
Vercel
Next.js
パフォーマンス
コスト最適化
フロントエンド
TypeScript
ISR

Vercel image-optimization guide: raise Core Web Vitals with next/image without making the bill spike

An image-optimization guide faithful to Vercel's official docs. With real code, it explains AVIF/WebP conversion and CDN caching via next/image, configuring remotePatterns/localPatterns, the cache key (q/w/url/Accept) and 31-day retention / minimumCacheTTL, the _next/image and _vercel/image URL formats, the mechanism of transformation billing (MISS/STALE), and how to keep costs down by drawing the line on 'which images to optimize / not optimize.'

Published
Reading time
6 min read
Author
友田 陽大
Share

Images are the heaviest and most LCP-affecting element on a web page. Optimize them and Core Web Vitals rise, improving SEO and bounce rate. On the other hand, misuse them and the bill spikes from transformation billing. Reconciling these two is the crux of Vercel image optimization.

This article summarizes the use of next/image and cost optimization, faithful to the official specs of Vercel Image Optimization. For the full picture, see the Vercel production-operations guide; for cost, Active CPU optimization.


The mechanism: dynamic transformation → CDN cache

Use next/image (Astro/Nuxt have equivalent components too) and Vercel dynamically optimizes the source image.

  1. Use a bare img tag and optimization is bypassed, serving the source image as-is.
  2. Use the Image component and it rides Vercel's optimization pipeline — conversion to AVIF/WebP, resizing to the device width, and CDN caching.
  3. Cache states:
    • HIT: served from cache (no transformation)
    • MISS: transform → cache → serve (transformation + cache write billing)
    • STALE: serve from cache while re-transforming in the background (same as above)
// app/page.tsx — next/image の基本
import Image from "next/image";
import hero from "@/public/hero.jpg"; // ローカル画像(ビルド時に解析)

export default function Page() {
  return (
    <Image
      src={hero}
      alt="製品のヒーロー画像"  // a11y意味のある alt を必ず
      priority                  // LCP 画像は priority で先読み
      sizes="(max-width: 768px) 100vw, 50vw" // レスポンシブの幅指定
    />
  );
}

An a11y essential: alt isn't decoration. Give meaningful images an alt describing the content, and decorative images alt="". It works for both the experience of screen-reader users and image SEO (web accessibility).


Configuration: narrow permissions with remotePatterns / localPatterns

State in next.config.ts which image sources may be optimized. Not allowing unlimited is important for both security and cost.

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    // ローカル(public 配下)
    localPatterns: [{ pathname: "/assets/images/**", search: "" }],

    // リモート(外部ホスト)
    remotePatterns: [
      {
        protocol: "https",
        hostname: "cdn.example.com",
        // 自分が所有しないホストは、乱用防止にアカウントID等を含める
        pathname: "/account123/**",
        search: "",
      },
    ],

    // 変換のバリエーションを絞る=キャッシュ効率とコストに効く
    formats: ["image/avif", "image/webp"],
    qualities: [75], // 品質を1つに固定するとキャッシュキーが減る
  },
};

export default nextConfig;

Abuse prevention: when allowing a hostname you don't own, include an account ID, etc., in the pathname to limit to your own source only. Widening the wildcard too much risks having your billing inflated by third-party transformations.


The cache key and retention

Optimized images are cached on the CDN, and if the cache key is the same, the transformation isn't re-run (= not billed). The key is:

  • Project ID
  • q (quality 1–100)
  • w (width px)
  • url (a content hash for local, the absolute URL for remote)
  • Accept header (normalized)

Retention:

TypeRetention
Local imageUp to 31 days on the CDN
Remote imageThe larger of the upstream Cache-Control max-age or minimumCacheTTL (default 3600s)

A redeploy doesn't invalidate the cache. Invalidate local images by "swapping the contents under the same name and redeploying," or by manual/programmatic purge. Once a remote image is cached, the old version keeps being served until expiry or purge. "I swapped the image but it's still old" is caused by this.

The transformation URL format

The Image component replaces src with an optimization URL.

  • Next.js: /_next/image?url={src}&w=3840&q=75
  • Nuxt/Astro, etc.: /_vercel/image?url={src}&w=3840&q=75

Cost optimization: don't make the bill spike

Image optimization is a regular "main cause of increased billing." In effective order.

① Don't optimize images that shouldn't be optimized

The following pass through with unoptimized and use no transformation quota.

  • Icons/thumbnails under 10KB (already small)
  • Animated images like GIF
  • SVG (vector; not a transformation target)
  • Frequently changing images (caching doesn't work and transformations keep running)
// 小さいアイコンや SVG は最適化しない
<Image src="/icon.svg" alt="" width={24} height={24} unoptimized />

② Narrow the variations

The cache key grows with the combination of q, w, and Accept. Fixing qualities to one (e.g. 75) and narrowing sizes/deviceSizes to only the needed widths reduces the number of unique transformations = billing, and raises the HIT rate.

③ Make caching effective

  • For remote images, extend minimumCacheTTL to reduce re-transformations (a trade-off with update frequency).
  • Transformation results persist across deploys, so don't purge unnecessarily.

④ See what's being consumed

In Observability's Image Optimization Insights, check the number of transformations, cache read/write, and Fast Data Transfer to identify heavy spots (observability).


When to use / not use

Should optimizeNo need to optimize
Product photos / hero images (large, high quality)Icons under 10KB
User-uploaded imagesAnimated GIF
Responsive images whose width changesSVG (vector)
Photo portfolios, etc., where the image is the starFrequently changing images

For user-uploaded images, the staple combination is to store with Vercel Blob (client upload) and optimize the display with next/image's remotePatterns.


Production checklist (image optimization)

  • Optimize photos/hero/uploaded images with next/image
  • Set alt by meaning (a11y, image SEO)
  • priority on the LCP image, sizes for responsiveness
  • unoptimized for small icons/SVG/GIF/frequently updated
  • Limit sources with remotePatterns/localPatterns, narrow the pathname for external
  • Narrow the variations of qualities and width (HIT rate ↑, billing ↓)
  • Understand cache invalidation (same-name swap or purge) when replacing images
  • Monitor the number of transformations and transfer volume in Observability

Summary

Image optimization is an area that creates "speed (CWV, SEO)" and "cost" at the same time.

  1. next/image for AVIF/WebP conversion, responsiveness, CDN caching
  2. Understand the cache key (q/w/url/Accept) and retention
  3. Cost is ① don't optimize unneeded images ② narrow the variations ③ make caching effective
  4. Limit sources with remotePatterns; a redeploy doesn't clear the cache
  5. Monitor consumption in Observability, and measure → optimize

I take on, as a project, tuning that raises CWV while keeping image cost down. This cluster's starting point is the Vercel production-operations guide.

This article is based on the Vercel Image Optimization official documentation (as of June 2026). Specs, billing, and limits are updated, so confirm the latest values officially at production adoption.

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Vercel apps, from design to production and cost optimization

Function design assuming Fluid Compute (safe global state, waitUntil, Cron), four-layer caching (ISR/CDN/Runtime Cache/Cache Components), safe deploys (preview/Promote/Instant Rollback/Rolling Releases), entry-point defense (Firewall/WAF/BotID), storage selection (Blob/Edge Config/Marketplace), and Active-CPU-billing-aware cost optimization. With experience running Next.js products on Vercel in production, I deliver fast, cheap, and secure.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading