An AI coding assistant will often recommend Vercel the moment it sees a Next.js project. That recommendation makes sense. Vercel removes most deployment work, gives every branch a preview URL, and handles the Next.js runtime without a custom server setup.
I followed that path and liked it. Then Vercel emailed me to say that my Hobby team had used 100% of its included 200,000 ISR Writes. Exceeding the allowance could pause the projects.
My blog contained 291 migrated posts, localized routes, category archives, search pages, and automated publishing tools. I first suspected traffic. The audit pointed somewhere else: the site had a cache lifecycle that allowed one content change to affect far more cached output than necessary.
Vercel was still a reasonable hosting choice. My implementation had never answered three operational questions: which content changed, which exact cache entries depend on it, and whether an unpublished draft should touch the public cache at all.
What Vercel ISR Writes measure
Incremental Static Regeneration lets Next.js serve cached pages while updating them after an interval or an explicit event.
Vercel stores ISR output in a durable cache. It measures reads and writes in 8 KB units. A stored response larger than 8 KB can therefore consume several units during one regeneration. A hypothetical 64 KB payload represents roughly eight units before compression and accounting effects.
Page count alone does not determine usage. Payload size, route count, cached representations, content changes, and invalidation scope all contribute.
Vercel also documents an important detail: a revalidation that produces the same content does not incur new ISR write units. Short revalidation intervals are therefore an incomplete explanation for high write usage.
The dangerous combination looks like this:
Time-based revalidation can still invoke background work. If the generated output changes, Vercel stores the new version. Vercel specifically recommends checking for values such as new Date or Math.random when unexpected ISR writes appear.
The cache pattern that put my project at risk
My audit found recurring ISR intervals across CMS-backed article, category, and marketing routes. The publishing layer could invalidate broad blog surfaces, while category pages handled more content than each response needed.
Draft operations also needed a clearer boundary. Saving an unpublished draft should not invalidate a public article, listing, category, or sitemap. Nothing visible changed.
The blog’s size made broad invalidation expensive by design. One article could affect:
Invalidating every blog surface after every mutation gave the system a poor upper bound. The problem grew with each imported article and locale.
Frequent production deployments created a second operational problem. Vercel can preserve ISR cache data between deployments, but a content workflow should not require a code deployment. Mixing editorial updates with releases made usage harder to diagnose and produced builds the site did not need.
I could not prove that one specific route created all 200,000 units from the available dashboard evidence. I could prove that the existing architecture allowed excessive regeneration, and I could remove that risk.
I replaced the clock with publication events
My new cache rule is direct: public caches change when public content changes.
I removed recurring ISR intervals from CMS-backed blog and static marketing routes. Cached data now stays valid until the write layer reports a relevant mutation.
Each cached query receives a narrow tag. The exact names vary by project, but the model includes separate tags for:
Publishing an article creates a cache plan from both the previous and new versions. The plan invalidates the article, its affected listings, its categories, and the sitemap. A changed slug or category also invalidates the previous public location.
Next.js recommends revalidateTag with the max profile for this pattern. It marks matching data as stale. The next visitor receives the cached response while Next.js refreshes the data in the background. One publication does not immediately launch a regeneration storm across every tagged page.
I use revalidatePath for exact public routes and cache tags for shared data. The two APIs solve different parts of the same problem.
Draft-to-draft updates now produce an empty cache plan. Publishing, unpublishing, changing a slug, or changing a category produces a scoped plan.
Server pagination reduced the cache surface
The original blog structure made large collections too easy to move through one response. I added server-side pagination and limited normal category pages to 12 article links.
After the change, production-style smoke tests returned:
The browser no longer needs hundreds of complete article records to render the first archive page. Smaller responses also mean fewer 8 KB write units when regeneration does happen.
At the configuration level, recurring CMS revalidation dropped to zero. The site can still create ISR writes after publication, which is intentional. One published article should refresh the small set of public surfaces that depend on it.
The Vercel checklist I now give AI agents
A successful deployment proves that the app builds. It does not prove that the cache strategy will remain within a free or paid usage budget.
I now ask an AI coding agent to complete this audit before shipping a content-heavy Next.js project:
A broad revalidatePath call against the whole site should require a concrete reason. “Something changed in the CMS” is not enough.
Should you leave Vercel for DirectAdmin?
I considered moving the site because I already had Node.js hosting through DirectAdmin.
That fallback is technically valid. Next.js documents that a single next start process can support Server Components, ISR, Server Actions, Cache Components, and the rest of the Node.js runtime. DirectAdmin documents Node.js applications through Nginx Unit.
A single instance with persistent disk is the easiest self-hosted setup. Multiple instances require shared cache storage and tag coordination. The reverse proxy must also support streaming if the app depends on progressive Server Component or PPR responses.
Self-hosting transfers responsibility to the operator. You own process supervision, logs, updates, backups, proxy behavior, cache persistence, and incident recovery. Existing server capacity can make the cash cost attractive, but engineering time belongs in the calculation.
I kept the project on Vercel after fixing the cache architecture. Vercel still gives me managed CDN caching, request collapsing, fast previews, rollbacks, and global invalidation. I now treat DirectAdmin as a tested exit path instead of an emergency reaction.
Vercel’s Hobby plan also targets personal, non-commercial projects. A commercial application should choose an appropriate paid setup even when its cache usage fits within the technical limit.
My takeaway
The AI recommendation covered deployment and missed the cache contract.
Vercel remains one of the fastest ways to ship Next.js. That convenience can hide infrastructure decisions until a usage warning forces you to inspect them.
My mistake was allowing time and broad mutations to control a large public cache. The fix was smaller and more precise:
Free hosting can work for a substantial content site when every public cache write has a reason. Design that lifecycle before importing hundreds of posts.


