5,000 resizes a month
Vercel’s free Hobby plan includes 5,000 image transformations a month, and Vercel emails the team as usage nears that limit. Sites with many large images reach it fastest.
The fix takes one short file and two lines of configuration: every picture gets resized by Sanity, the content platform that already stores it.
How Vercel counts resizes
Next.js sends each visitor a picture sized for their screen: a narrow copy for a phone, a large one for a wide monitor, so a single photo can exist in up to 16 widths. On Vercel, the default Next.js picture path runs through Vercel’s own resizer, and each new combination of picture, width and quality counts once toward the monthly allowance. Preview deployments count too.
The count multiplies fast. A shop page with 100 product photos offers each in up to 16 widths, 1,600 possible resizes, so three such pages pass the monthly 5,000.
At 100%
Hobby keeps the bill at zero. The cost lands on the page instead: each picture still waiting for its first resize returns status 402, and the visitor sees its description text where the photo should be. Pictures resized earlier keep loading, so new products and new pages show empty frames first.
Pictures straight from Sanity
Pictures stored in Sanity can skip that resizer, since Sanity’s image CDN resizes on request. Next.js documents a way to hand picture work to a service like that, a custom image loader, and lists Sanity among its examples. The loader is one short file, here data/imageLoader.js:
'use client'
export default function imageLoader({ src, width, quality }) {
if (!src.startsWith('https://cdn.sanity.io/') || /\.(svg|gif)(\?|$)/i.test(src)) return src
const [base, query = ''] = src.split('?')
const params = new Map(
query
.split('&')
.filter(Boolean)
.map((pair) => {
const at = pair.indexOf('=')
return at < 0 ? [pair, ''] : [pair.slice(0, at), pair.slice(at + 1)]
}),
)
const w = Number(params.get('w'))
const h = Number(params.get('h'))
if (w && h) params.set('h', String(Math.round((h * width) / w)))
params.set('w', String(width))
if (!params.has('q')) params.set('q', String(quality || 75))
if (!params.has('fit')) params.set('fit', 'max')
if (!params.has('auto')) params.set('auto', 'format')
return `${base}?${[...params].map(([k, v]) => (v ? `${k}=${v}` : k)).join('&')}`
}And two lines in next.config.mjs point Next.js at it:
images: {
remotePatterns: [{ protocol: 'https', hostname: 'cdn.sanity.io' }],
loader: 'custom',
loaderFile: './data/imageLoader.js',
},For every width a picture offers, the loader returns a Sanity address with:
- w, the width the screen needs
- q=75, unless the address already sets a quality, such as 100 for a full-screen view
- fit=max, so a picture stays at or below its original size
- auto=format, so Sanity sends WebP or AVIF wherever the browser takes it
Crops and focus points already in the address ride along, and a fixed cut with both width and height keeps its shape at every width. SVG icons, GIFs and files served from the site itself load as they are.
Default path and loader
| Default path | Custom loader | |
|---|---|---|
| Who resizes the pictures | Vercel | Sanity’s image CDN |
| What counts toward Vercel’s 5,000 | Each new picture, width and quality | Zero |
| Monthly limit in play | 5,000 transformations | 100 GB of Sanity bandwidth |
What stays private
Pictures in Sanity are already public on cdn.sanity.io, so the change alters only which address asks for them. Picture addresses carry zero keys, the Sanity write token stays on the server, and a site with a Content Security Policy lists cdn.sanity.io among its image sources.
The trade-off
Picture bandwidth moves from Vercel’s meter to Sanity’s. Both free plans allow 100 GB a month, and Sanity’s resizing draws on that bandwidth alone.
Sanity’s free plan stops serving at its cap and emails at 80%, so an early warning stays in place. Every site reading from the same Sanity project draws on the same 100 GB.
When the default fits
The default Next.js picture path suits a site of a few pages and a handful of pictures. A shop, a gallery or a growing catalogue multiplies the pictures, and the loader is best added before the first usage email, while every picture still loads.
Websites & AppsSites, stores and web apps on Shopify, Framer, Webflow or custom code, integrations with CMS, CRM and more, servers, and security.Sources
- Published
- Author
- Booban Net.
- Category
- Websites & Apps
- Service
- Custom websites




