As a website owner, I'm constantly iterating on my personal site—upgrading to new versions and experimenting with different technologies and architectures. Recently, I encountered a warning from Vercel indicating that I was approaching my free tier limit for 'Image Optimization – Transformation.' After some trial and error, I found a solution that keeps my usage within the free tier. In this article, I'll break down the problem, how I identified the root cause, the options I considered, and the approach I ultimately implemented.
The Problem: Hitting Vercel's Image Optimization Cap
My current website, now in its fifth version (as of 2026), leverages Cloudflare R2 Object Storage for CDN delivery and is heavily optimized for both traditional web search and AI-driven search. You can visit it at fahimbinamin.com to see the latest version.
Because version 5 is a multi-page site, I consolidated all my writing—previously scattered across various platforms—into one cohesive space. I wanted each article to maintain its canonical URL integrity, so search engine and AI crawlers would recognize the original published source. This feature was a key addition to version 5.
The site runs on Next.js and fully utilizes Next's built-in image optimization protocol. However, the codebase is closed-source, so the specific implementation isn't publicly accessible.
Pinpointing the Cause
After receiving the warning, I dug into Vercel's dashboard to understand what was consuming my image transformation quota. The issue was that every image request triggered a transformation, even for images that had already been optimized in previous versions. This included legacy images from older site versions that hadn't been updated or properly cached.
Additionally, I noticed that some images with query parameters—like those used for resizing or format conversion—were being processed repeatedly, generating unnecessary load on the free tier.
Options for Resolution
When facing this cap, I considered several approaches:
- Optimize images at the source: Before uploading to Cloudflare R2, I could compress and resize images manually to reduce the need for runtime transformations.
- Leverage a dedicated image CDN: Services like Cloudinary or imgix offer specialized image optimization and often integrate seamlessly with Next.js.
- Implement custom caching: By configuring a custom cache layer between Next.js and the image optimizer, I could reduce redundant transformations.
- Upgrade Vercel plan: The simplest but least cost-effective option, especially for a personal site.
- Pre-optimization: I batch-processed all existing images to ensure they were compressed to the optimal format (e.g., WebP) and resolution, reducing the need for runtime transformations.
- Enhanced caching: I configured Next.js to use a longer cache TTL for optimized images, allowing Vercel's edge network to serve cached versions without hitting the transformation quota again.
- Audit your image usage: Identify which images are being optimized and how often.
- Optimize at the source: Compress and resize images before uploading to your storage/CDN.
- Configure caching: Increase the cache TTL for optimized images to reduce redundant transformations.
- Consider alternative CDNs: Services like Cloudinary or imgix can offload the optimization burden entirely.
My Chosen Solution
After evaluating the trade-offs, I decided to implement a two-pronged strategy:
Implementation Details
For pre-optimization, I used a simple script with sharp to resize and compress images before uploading to Cloudflare R2. This reduced the file size by over 60% on average.
For caching, I updated the next.config.js to set images.minimumCacheTTL to 31536000 (one year). This ensures that once an image is optimized, it's cached at the edge and rarely re-transformed.
Key Takeaways
If you're approaching Vercel's image optimization cap, consider these steps:
By implementing these changes, I've kept my Vercel usage well within free tier limits, and the site's performance has actually improved due to smaller image payloads and better caching. If you're facing a similar issue, I hope this guide helps you find a sustainable solution.
via FreeCodeCamp
