When Next.js Is the Wrong Choice: The Lim­its Hon­est Ad­vi­sors Name

Next.js is ex­cel­lent — and for a whole class of projects it's the wrong call. An hon­est bound­ary for de­ci­sion-mak­ers: ov­erengi­neer­ing, mi­gra­tion costs, and the point where I'd pick it any­way.
9 min readMatthias RadscheitMatthias Radscheit
Happycodingen-US

TL;DR

For pure marketing sites Next.js is often overengineering; for teams without React experience it's expensive to onboard; on tiny budgets the operational load is out of proportion. Astro, Vite or a classic CMS are then the more honest pick. If you're growing and betting on React, Next.js still wins.

  • For static marketing sites Next.js carries framework weight that Astro avoids by shipping 0 JS by default — overengineering is real, but rarely the most expensive mistake.
  • The App Router migration and the breaking changes in v15/v16 are a concrete, underestimated cost line, not a changelog footnote.
  • Teams without React competence pay the learning curve twice: in the build and in operations. That's a hiring question, not a tech question.
  • Self-hosting lowers licence costs but shifts operational responsibility — for tiny budgets that's a bad trade.
  • The boundary is not a formula: time horizon and team decide whether the bet on the Next.js ecosystem pays off even for small projects.

Next.js is an ex­cel­lent choice — and for a whole class of projects it's still the wrong one. Any­one who won't say that out loud is sell­ing a frame­work as a re­li­gion. And de­ci­sion-mak­ers who have al­ready lived through a mi­gra­tion can smell the gap be­tween promise and re­al­i­ty from across the room.

We build Next.js ap­pli­ca­tions, run them self-host­ed, and pitch them at de­ci­sion-mak­er lev­el. That's ex­act­ly why this ar­ti­cle ex­ists: a tech­nol­o­gy whose lim­its you can't name is one you haven't un­der­stood. The hon­est an­swer to the ques­tion of when Next.js is the wrong choice is what makes the rec­om­men­da­tion in every oth­er case cred­i­ble. There are three con­stel­la­tions where I ad­vise against it — and one case where I con­tra­dict my­self. For the larg­er pic­ture this de­ci­sion be­longs in, see our overview of front-end ar­chi­tec­ture for mid-sized com­pa­nies.

When Next.js is the wrong choice: ov­erengi­neer­ing a mar­ket­ing web­site

The most com­mon bad de­ci­sion is­n't the most ex­pen­sive, but it is the most vis­i­ble: Next.js for a pure mar­ket­ing web­site. A dozen pages, a bit of ed­i­to­r­i­al con­tent, a con­tact form, no logged-in area, no serv­er-side busi­ness log­ic. For some­thing like that, Next.js brings frame­work weight the user pays for in the brows­er.

The tech­ni­cal core: Next.js is a Re­act frame­work. Even a large­ly sta­t­ic page car­ries router and hy­dra­tion code with it. Com­par­i­son blogs put a Next.js mar­ket­ing site at rough­ly 80–150 KB of JavaScript de­pend­ing on set­up, while As­tro ships 0 KB by de­fault and only loads JavaScript where a com­po­nent is gen­uine­ly in­ter­ac­tive. Those KB fig­ures are rules of thumb, not pri­ma­ry bench­mark data — but the or­der of mag­ni­tude holds. As­tro pro­duces sta­t­ic HTML, has no hy­dra­tion oblig­a­tion, and is con­cep­tu­al­ly lean­er for con­tent-heavy pages. For a site that stays pre­dictably small, that's the more hon­est choice.

Here I have to qual­i­fy, or I'll be un­fair. Next.js it­self of­fers an SPA and sta­t­ic mode, and Serv­er Com­po­nents cut the JavaScript sent to the brows­er sub­stan­tial­ly — only com­po­nents marked with 'use clien­t', to­geth­er with their im­port graph, reach the client bun­dle at all. Used with dis­ci­pline, Next.js gets far clos­er to As­tro than the raw num­bers sug­gest. The point is not that Next.js is slow. The point is that for a task As­tro solves with few­er mov­ing parts, you learn, op­er­ate and main­tain a larg­er frame­work across its ver­sions. Com­plex­i­ty is a cost line even when it car­ries no li­cence fee.

For ed­i­to­ri­al­ly dri­ven sites there's a third path de­vel­op­ers like to over­look: a clas­sic or head­less CMS where non-de­vel­op­ers main­tain con­tent with­out a de­ploy pipeline. Whether you're build­ing a plat­form or a pub­li­ca­tion de­cides more than any frame­work bench­mark. Draw the line clean­ly be­tween a con­tent sys­tem and an ex­pe­ri­ence plat­form and the ar­chi­tec­ture al­most picks it­self — some­thing we've writ­ten about at more length, in­clud­ing the dif­fer­ence be­tween a CMS and a DXP.

Next.js draw­backs: break­ing changes as a real cost line

The sec­ond rea­son to ad­vise against it ap­pears nowhere in the sales brochure: Next.js has an ac­tive de­vel­op­ment cy­cle with gen­uine break­ing changes. That's not an ac­cu­sa­tion — a frame­work that moves stays rel­e­vant. But move­ment costs, and those costs land in your main­te­nance bud­get, not in mar­ket­ing.

Con­crete­ly: ver­sion 15 made cook­ies, head­ers, params and search­Params asyn­chro­nous, made Re­act 19 manda­to­ry, and stopped caching fetch by de­fault. With ver­sion 16, syn­chro­nous ac­cess to those re­quest APIs was re­moved en­tire­ly, Node.js 20.9+ be­came manda­to­ry, and Tur­bopack be­came the de­fault — a build with its own web­pack con­fig­u­ra­tion sim­ply fails with­out the --web­pack flag. Add changed next/im­age de­faults and fur­ther ad­just­ments. No sin­gle re­lease is dra­mat­ic, but it adds up: run a Next.js ap­pli­ca­tion across three or four years and you take on reg­u­lar up­grade main­te­nance that a sta­t­ic As­tro build or a host­ed CMS just does­n't have.

One wide­spread mis­con­cep­tion de­serves cor­rect­ing here, be­cause it poi­sons the dis­cus­sion so of­ten: Next.js 16 does not abol­ish mid­dle­ware. It's re­named to proxy and dep­re­cat­ed, then runs on the Node.js run­time. If you need the Edge run­time, the docs say you can still use mid­dle­ware. Any­one telling you mid­dle­ware has "gone away" has­n't read the changel­og. Pre­ci­sion on de­tails like this is the dif­fer­ence be­tween a risk as­sess­ment and pub talk.

What does the App Router mi­gra­tion re­al­ly cost?

The most un­der­es­ti­mat­ed item is the App Router mi­gra­tion. Many teams start­ed in 2023 and 2024 ex­pect­ing the move off the Pages Router to be a con­fig­u­ra­tion mat­ter. It is­n't.

Next.js it­self rec­om­mends an in­cre­men­tal, page-by-page mi­gra­tion and, in its own mi­gra­tion docs, speaks open­ly of new con­cepts, men­tal mod­els and be­hav­iour­al changes to be learned. That's ven­dor lan­guage for: this is work. Forced changes in­clude get­Server­Side­Props and get­Sta­t­icProps to async Serv­er Com­po­nents, get­Sta­t­ic­Paths to gen­er­at­eSta­t­ic­Params, _app and _doc­u­ment to app/lay­out.js, next/head to the Meta­da­ta API, pages/api to Route Han­dlers, and next/router to next/nav­i­ga­tion. Each of those lines gets ex­plained in pass­ing — in a grown code­base, each one is refac­tor­ing with a test­ing bur­den at­tached.

Real-world re­ports con­firm it. One en­gi­neer­ing team de­scribed run­ning Pages and App Router in par­al­lel as drawn-out, had to switch er­ror han­dling en­tire­ly to Er­ror Bound­aries, and could no longer use the run­time con­fig they'd re­lied on be­fore. The men­tal mod­el of RSC caching — when some­thing is sta­t­ic, dy­nam­ic or reval­i­dat­ed — is the ac­tu­al learn­ing curve, not the syn­tax. In a much-watched GitHub dis­cus­sion, a clear ma­jor­i­ty of more than 2,000 par­tic­i­pants vot­ed for the Pages Router. That poll is self-se­lect­ing, opin­ion­at­ed and part­ly over­tak­en by new­er ver­sions — as proof of a ma­jor­i­ty it does­n't hold. As a sig­nal that the switch cre­at­ed fric­tion, it's worth tak­ing se­ri­ous­ly.

For you as a de­ci­sion-mak­er that means: if a ser­vice provider quotes a Next.js mi­gra­tion with­out a sep­a­rate line for the router switch, check the num­bers. A clean first im­ple­men­ta­tion of a self-host­ed Next.js stack runs us a one-off 5,000 to 20,000 eu­ros; a mi­gra­tion with sub­stan­tial Pages Router lega­cy can ex­ceed that, be­cause it's refac­tor­ing rather than a new build. Any­one who wants to go from pitch to go-live in 90 days plans such con­ver­sions in rather than dis­cov­er­ing them mid-project — we've de­scribed what that looks like in our ac­count of the path from pitch to go-live.

When is Next.js the wrong choice for a team?

The third case is a hir­ing ques­tion, not a tech ques­tion. Next.js is Re­act. If your team lives in a dif­fer­ent stack — Vue, clas­sic serv­er-side ren­der­ing, a Java world — you pay the learn­ing curve twice: once in the build, once per­ma­nent­ly in op­er­a­tions.

The mar­ket does favour Re­act. In the Stack Over­flow De­vel­op­er Sur­vey 2025, some­where be­tween a third and near­ly half of re­spon­dents used Re­act, well ahead of An­gu­lar, and among pro­fes­sion­al de­vel­op­ers Re­act leads more clear­ly still. De­vel­op­er avail­abil­i­ty is there­fore strate­gi­cal­ly on Re­ac­t's side. But the mar­ket av­er­age does­n't help your spe­cif­ic team if it can't write Re­act to­day. In­tro­duc­ing a frame­work whose men­tal mod­el — Serv­er vs. Client Com­po­nents, caching be­hav­iour, hy­dra­tion — no­body in­ter­nal­ly car­ries cre­ates a ven­dor lock-in at the ser­vice-provider lev­el that rarely gets priced in. You're then buy­ing not just code, but the ne­ces­si­ty of keep­ing that provider.

And there's the bud­get bound­ary. Self-host­ing on Het­zn­er is GDPR-com­pli­ant in Ger­many from rough­ly 20 to 50 eu­ros a month, with op­er­a­tions cost­ing two to five hours month­ly for up­dates, mon­i­tor­ing and back­ups. That's cheap — but it's op­er­a­tional re­spon­si­bil­i­ty. For a tiny project on a tight bud­get that's ex­act­ly the bad trade: the saved plat­form costs get eat­en by op­er­at­ing time, and the gen­uine­ly hard part of self-host­ed Next.js — ISR caching across mul­ti­ple in­stances with a cus­tom cacheHan­dler — is rarely need­ed in small se­tups, yet still has to be un­der­stood the mo­ment you scale. We've laid out the whole plat­form-ver­sus-self-host­ing trade-off in our com­par­i­son Next.js on Het­zn­er in­stead of Ver­cel.

The un­com­fort­able part: some­times I take Next.js any­way

Now I'll con­tra­dict my­self, de­lib­er­ate­ly. In sev­er­al of the cas­es where Next.js looks wrong by these cri­te­ria, I'd still choose it.

Take the "sim­ple" mar­ket­ing web­site. It grows sur­pris­ing­ly of­ten. Five pages be­come a cus­tomer por­tal, the con­tact form be­comes a lo­gin, the pub­li­ca­tion be­comes a plat­form. Pick the As­tro or web­site-builder path ear­ly and you re­pay that bet lat­er with a mi­gra­tion — and a mi­gra­tion af­ter three years of growth costs more than the ini­tial ov­erengi­neer­ing ever would. The bet on the Re­act and Next.js ecosys­tem can be right for pre­cise­ly the project that looks too small for it to­day.

Then there's hir­ing and con­ti­nu­ity. For Re­act you find de­vel­op­ers, li­braries, pat­terns and an­swers. That's a real val­ue that out­weighs a mo­men­tary learn­ing curve. When I choose be­tween the the­o­ret­i­cal­ly bet­ter-fit­ting niche tool and the frame­work I can still staff in two years, the ecosys­tem of­ten wins — even against my own ov­erengi­neer­ing cri­tique. Per­for­mance is rarely the counter-ar­gu­ment here: with Serv­er Com­po­nents and ISR, a clean­ly built Next.js de­liv­ers good Core Web Vi­tals that ul­ti­mate­ly feed through to con­ver­sion and rev­enue.

The bound­ary is there­fore not a for­mu­la. It's a weigh­ing of time hori­zon and team. A throw­away project with fixed scope and a Vue team: not Next.js. A plat­form with un­clear growth, a Re­act-lean­ing team and a hori­zon mea­sured in years: al­most al­ways Next.js, even if it starts small to­day.

What I tell de­ci­sion-mak­ers

Ask two ques­tions be­fore you or­der Next.js or re­ject it. First: is this go­ing to grow? If the an­swer is an hon­est no — a cam­paign mi­crosite, a brochure, a project with an end date — take As­tro, Vite or a CMS and spare your­self the frame­work and the mi­gra­tion risk. Sec­ond: who car­ries this? If no­body in-house can write Re­act and no­body is meant to learn it, you're buy­ing a ven­dor lock-in with Next.js that costs more than any li­cence.

If every­one in­volved says yes to both — it's grow­ing, and we can or want to car­ry Re­act — then Next.js is al­most al­ways right, and the break­ing changes and the mi­gra­tion be­come a priced-in main­te­nance line, not a deal-break­er. Dis­trust any provider who sells you Next.js for every­thing, and equal­ly any who damns it whole­sale. The right an­swer has a date, a team and a time hori­zon. Who­ev­er names the lim­its has un­der­stood what they're rec­om­mend­ing — and that's ex­act­ly who I'd be­lieve.

Frequently asked questions

Is Next.js overkill for a simple marketing website?
In many cases, yes. A pure marketing site with a few dozen pages needs neither server-side data logic nor hydration for interactive components. Astro ships 0 JavaScript by default and produces static HTML; comparison blogs put a Next.js marketing site at roughly 80–150 KB of JS depending on setup, against nearly 0–20 KB for Astro. If the site stays predictably small, Astro or a classic CMS is the leaner choice. If it's likely to grow into a platform, Next.js can still be right.
How expensive is the migration from the Pages Router to the App Router?
It's not a changelog detail, it's a project line item. Next.js itself recommends an incremental, page-by-page migration and speaks openly of new concepts and mental models a team has to learn first. Forced changes include moving getServerSideProps and getStaticProps to async Server Components, next/head to the Metadata API, and next/router to next/navigation. Teams report that running both routers in parallel and switching error handling to Error Boundaries cost significant time.
What's the best Next.js alternative for small projects?
There isn't one alternative, there are three, depending on the case. For content-heavy, mostly static sites: Astro. For a lean single-page app with no SEO pressure: Vite with React or Vue. For editorially driven sites maintained by non-developers: a classic or headless CMS. The choice depends on who maintains the site, how much it grows, and what front-end competence the team already has.
Is self-hosting Next.js worth it on a small budget?
Rarely. Self-hosting lowers licence costs over time but shifts operational responsibility onto your own team — updates, monitoring, backups. For a tiny project on a tight budget that trade is often bad, because the saved platform costs get eaten by two to five hours of operations a month. Self-hosting pays off when data sovereignty, scaling or medium-term cost reduction matter — not as a cost-cutting measure for the smallest setup.

Sources

Related articles

Open for select projects

Let's talk about your project

Book a no-oblig­a­tion call, send us an email, or use the form – we'd love to hear from you.

150+
Completed projects
15
Years of experience
8
Senior‑level team members