vercel · pricing · tutorial

Vercel Image Bills Burned Us: Cut Them 80%

next/image transforms meter per variant on Vercel. AVIF, responsive sizes, long TTLs, and edge caching cut the line 80%. The playbook inside.

A busy sheep-shearing shed with shearers at work, painted in 1890
A busy sheep-shearing shed with shearers at work, painted in 1890 · Photo: Tom Roberts, public domain, via Wikimedia Commons

The image bill bigger than hosting

A photography-heavy marketplace: 2,000 product images, responsive next/image everywhere, decent traffic. Month's end: the Image Optimization line alone beats the old VPS bill — transforms in the millions, cache writes stacking, each variant billed like a tiny deployment.

Nobody approved this. Developers used the documented component correctly. The meter priced each correctness separately: per source image, per width variant, per format negotiation, plus cache read/write operations underneath.

Vercel image optimization bill pain is the meter most teams discover last because images feel free — they're just files. On metered transforms, they're tiny invoices wearing file clothes.

Where image money actually goes

Source What meters Typical multiplier
Width variants Transform per size 5–8x per upload
Format negotiation AVIF/WebP per variant 2x on top
Cache writes First-gen per variant 1x, then reads
Cache reads Every served variant Ongoing per view
Source allowance ~5k images on Pro (verify) Over-quota per thousand

Three details multiply the damage:

  1. Responsive markup multiplies uploads. sizes with six breakpoints turns one product photo into six transforms minimum — times two formats, times cache operations. A 2,000-image catalog becomes 24,000+ metered units before a single visitor arrives. Pre-generation at build time doesn't help; it just front-loads the bill.
  2. Unoptimized uploads compound. A 8MB camera original transforms slower and bigger than a 200KB pre-compressed input — same visual result, multiples of meter. Every byte uploaded raw gets transformed, cached, and served at premium size. Compression belongs at upload, not at edge.
  3. Short TTLs re-bill served images. Default cache lifetimes revalidate variants constantly, turning one-time transforms into recurring reads. Year-long immutable caching (hashed filenames) converts repeat views to $0 — the single highest-leverage line in this post.

The $1,800-exit post named images the silent killer. This one defuses them.

Vercel image optimization bill cut

In-platform first (stay), flat-hardware escape second (when meters persist).

Step 1 — Shrink inputs before they meter.

next.config.js
images: {
  formats: ["image/avif", "image/webp"],   // modern first, smallest bytes
  deviceSizes: [640, 1080, 1920],          // 3 widths, not 8 (audit your CSS)
  imageSizes: [64, 128, 256],              // icons small, deliberate
  minimumCacheTTL: 31536000,               // immutable: cache for a year
},
// upload pipeline: compress to <300KB + strip EXIF before storage, always

Three widths cover real layouts (audit breakpoints — most sites use three, declare eight). AVIF-first halves bytes over JPEG at equal quality. Pre-compressed inputs mean transforms process kilobytes, not megabytes. Input discipline cuts the meter at its root: fewer, smaller source operations.

Step 2 — Cache like the bill depends on it (it does).

filenames: content-hashed (app-3f9a2c.avif) → immutable forever
headers: Cache-Control: public, max-age=31536000, immutable
edge: Cloudflare in front caches variants globally (origin transform once)

Hashed filenames make immutability safe (changed image = new hash = new URL, zero staleness). Year-long headers stop revalidation churn. Edge caching converts the origin transform into a one-time event per variant globally — subsequent views worldwide cost nobody anything. Cache architecture is billing architecture wearing a performance costume.

Step 3 — Move serving flat when transforms dominate.

# same images, $5 VPS: Nginx serves pre-built variants from disk
# build-time script generates 3 widths × AVIF/WebP once (local CPU, $0)
# Cloudflare caches globally; origin meter: none exists
# trigger: image line past ~$100/mo sustained → the weekend migration pays back in weeks

Pre-generated variants on disk plus edge cache equals the transform pipeline with zero per-unit meter. The $100/mo image-line threshold is the honest trigger — below it, optimize in place (steps 1–2 recover most); past it, flat serving's payback window is weeks. Meters deserve exits, not just efficiency.

It all holds together — pixels without per-variant invoices.

The image-line diet

Measure Before After steps 1–2
Variants per upload ~16 (8 widths × 2 formats) 6 (3 × 2)
Avg source size 2–8MB camera raw <300KB compressed
Cache lifetime Default (revalidating) 1 year immutable
Repeat-view cost Metered reads $0 (edge hits)
Total image line Baseline $$$$ ~20% of baseline

Worth saying plainly: fewer widths risk edge-case layouts (audit CSS first, add back widths with evidence), AVIF encoding costs build CPU (pennies locally, meters remotely — hence flat), and immutable caching demands hashed-filename discipline (forget once, serve stale faces for a year).

BoringPush prices discipline against meters: filename hygiene is free, transforms are forever. Cheap rigor, expensive laxity.

FAQ

Does vercel image optimization bill cut work without leaving Vercel?

Yes — steps 1–2 are platform-native and recover ~80% regardless of host. Leaving (step 3) is for sustained high-volume lines past ~$100/mo, where per-unit economics beat any optimization. Optimize first everywhere (weeks of runway), exit second only on proof. Most image bills die at step 2; step 3 exists for catalogs, not blogs.

Should I use a dedicated image CDN (Cloudinary, Imgix) instead?

Same meter, different logo: per-transform pricing with better tooling and worse lock-in (URLs embed vendor syntax across your content). Dedicated CDNs win on transformation features (cropping APIs, art direction); they lose on the same unit economics plus migration friction. Self-serve variants plus edge cache match 90% of needs at flat cost. Features you use justify vendors; features you admire don't.

How do user-uploaded avatars fit the pre-compression rule?

Compress client-side before upload (browser Canvas API → <100KB WebP) plus server-side validation (dimensions, type, size caps). Avatars are the highest-volume untrusted input — uncompressed 5MB selfies from phones are the classic meter bomb. Client compression is UX (fast uploads) plus billing (small transforms) in one line of code. Never accept raw camera bytes from users.

What about next/image placeholders (blur) — do they meter?

Blur placeholders generate tiny transforms (negligible) but the blurDataURL build-time generation adds build minutes on large catalogs. Static imports handle it at build; remote images need explicit blur data or the shimmer fallback. Placeholder cost rounds to zero against variant math — optimize variants first, admire placeholders later (they're free-ish either way).

Can I pre-generate variants at build time on Vercel?

Technically yes, economically pointless: build-time generation still consumes build minutes and cache writes on metered infrastructure. Pre-generation pays on flat hardware (local CPU, $0 marginal) and costs on meters. Match the optimization to the host: lean configs on Vercel, pre-generation on VPS. Right trick, wrong host is still wrong.

When do images justify the VPS move alone?

Sustained image line past ~$100/mo with catalog growth (marketplaces, UGC, photography) — payback in weeks, plus the bandwidth and request meters fall in the same migration. Single-meter exits are rare; image-heavy apps usually drag bandwidth along (the $1,800 anatomy shows the bundle). Migrate on the bundle math, credit images as the trigger.

Keep reading

+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)

The Agent-First Shipping Kit

Command from your phone.

Built so autonomous AI agents build what you want without breaking what's already paying you.

$199

Get BoringPush

One-time payment · Lifetime updates · Unlimited projects.

Keep reading