Skip to the solution
MediumFrontend8 min read

What changed for next/image defaults in Next.js 16?

1.0k views

The problem

Question presented to candidate: "After upgrading to Next.js 16, some of our images return 400, thumbnails look slightly different, and our image CDN bill went down. What changed in the next/image defaults, why, and how would you restore old behaviour where you really need it?"

What a strong answer should cover:

  • images.qualities now defaults to [75]: other quality props are coerced to the closest allowed value, and direct /_next/image requests with another q return 400.
  • 16 was removed from images.imageSizes; w=16 returns 400 unless you add it back.
  • minimumCacheTTL went from 60 seconds to 4 hours (14400) to cut revalidation cost for images without cache headers.
  • Local images with query strings need images.localPatterns with a search value; remote images resolving to private IPs are blocked unless dangerouslyAllowLocalIP: true (an SSRF trade-off); maximumRedirects defaults to 3.
  • priority is deprecated in favour of preload (or loading="eager" / fetchPriority="high"); images.domains and next/legacy/image are deprecated.

Clarifying questions expected:

  • "Do we request /_next/image URLs directly, for example from emails or a CMS?" β€” those break first.
  • "Do any images come from internal hosts or need several qualities?" β€” that decides the opt-ins.

Code / implementation expected: Yes β€” a next.config.ts images block that re-enables what the app needs.

  • nextjs
  • image
  • performance
  • next-16

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 8 sections

Read the code

next.config.ts: opting back in, deliberately
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    qualities: [50, 75], // default [75]
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // default drops 16
    minimumCacheTTL: 60, // default 14400 (4 hours)
    localPatterns: [
      { pathname: "/photo.png", search: "" }, // the bare URL must be listed too
      { pathname: "/photo.png", search: "?v=1" },
    ],
    remotePatterns: [{ protocol: "https", hostname: "images.example.com" }], // replaces images.domains
    // dangerouslyAllowLocalIP: true, // only for private networks (SSRF risk)
  },
};

export default nextConfig;
The lab page (preload, a coerced quality, sizes, and the deprecated priority)
import Image from "next/image";

export default function Page() {
  return (
    <main>
      <Image id="hero" src="/photo.png" alt="Hero" width={800} height={400} preload />
      <Image id="thumb" src="/photo.png" alt="Thumb" width={48} height={24} quality={50} />
      <Image id="resp" src="/photo.png" alt="Responsive" width={2000} height={1000} sizes="33vw" />
      <Image id="old" src="/photo.png" alt="Old" width={64} height={32} priority />
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 29 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

How do you read cookies and headers in Next.js (cookies(), headers())?

Continue