I need to tell you about the worst debugging session of my life.
Three hours. A production bug. Users couldn't check out. Revenue bleeding by the minute.
The bug was in our data fetching layer. Somewhere between a Server Component, a Server Action, and a client component that needed the same data — something had broken. I couldn't tell where the data was loading. I couldn't tell what was running on the server and what was running on the client. I couldn't even reproduce it locally.
Three hours of staring at Next.js App Router code that I had written myself — and I genuinely could not understand what it was doing.
That was the day I started looking for something else.
I Used to Love Next.js
Let me be clear about something before I tell you what I switched to.
Next.js is not bad. It's genuinely impressive engineering. The team at Vercel has built something remarkable — React Server Components, Server Actions, automatic code splitting, image optimization, a deployment experience that is still the smoothest in the industry.
For two years, Next.js was my default. Every new project started with npx create-next-app. It was the safe choice. The professional choice. The choice that nobody ever got fired for making.
I recommended it to every developer who asked me what to use.
And then App Router happened.
When Next.js Stopped Feeling Like Home
When Next.js 13 dropped the App Router, I was genuinely excited.
Nested layouts. React Server Components out of the box. Automatic optimization. It sounded like the future of React development.
For the first month, it was smooth.
Then the complexity started showing up in small ways.
A component that needed to be a Server Component for performance but a Client Component for interactivity. A data fetch that worked in development but failed in production because of how the edge runtime handled certain Node.js APIs. A caching behavior that was supposed to be automatic but was caching things I didn't want cached — and not caching things I did.
The App Router was one abstraction too far.
Every time something broke, I had to mentally trace through invisible layers — is this running on the server? On the client? On the edge? Is this cached? For how long? Why?
The framework was doing things I hadn't asked it to do. And when those things broke, I had no map to navigate by.
The Production Incident That Changed Everything
Back to that three-hour debugging session.
The bug: our checkout flow was intermittently failing. Users would add items to their cart, proceed to checkout, and get a blank screen.
The cause — when I finally found it, four hours later: a race condition between a Server Action updating cart state and a Server Component that was reading that state. The Server Component was being cached aggressively by Next.js's automatic caching layer. The cache wasn't invalidating correctly after the Server Action ran.
The fix was two lines.
Finding those two lines took four hours — because I didn't fully understand what the framework was doing behind the scenes.
We went so far into framework abstraction that we forgot what it felt like to just write React.
That night, I opened a new browser tab and searched: "Next.js alternatives 2026."
What I Found — And Why TanStack Start Won
I spent two weeks researching alternatives. Seriously researching — building small projects, reading docs, watching conference talks.
Here's what I evaluated:
Remix / React Router v7 — Great web standards approach. But Remix merged into React Router v7 in late 2024, and the ecosystem felt uncertain. Also, same Magic Convention problem as Next.js, just different magic.
Astro — Incredible for content sites. Not what I needed for a data-heavy React app with complex client interactions.
SvelteKit — Genuinely beautiful. But switching meant leaving React entirely. Not a conversation I was ready to have with my team.
TanStack Start — This one stopped me.
Many devs say that once they start using TanStack Start, they forget they're even in a framework. It feels like normal React with some helpful extras.
I built a small project with it on a Saturday afternoon.
By Sunday morning, I had shipped more than I expected — and I understood every line of what I had written.
That feeling — of understanding your own code — is something I had quietly stopped expecting from a framework.
The Stack I Use Now
After two months of production use, here's exactly what replaced Next.js in my workflow:
The Core: TanStack Start + TanStack Router
// Everything is explicit. Nothing is magic.
const Route = createFileRoute('/products/$productId')({
loader: async ({ params }) => {
// You can see exactly where data loads
// You know exactly when it runs
// TypeScript knows exactly what it returns
return fetchProduct(params.productId);
},
component: ProductPage,
});
function ProductPage() {
const product = Route.useLoaderData();
// product is fully typed — no casting, no guessing ✅
return <div>{product.name}</div>;
}
TanStack Start's routing is fully type-safe at compile time. Route parameters, search params, and navigation calls are validated by TypeScript before your code runs.
Compare this to Next.js where useParams() returns { [key: string]: string | string[] | undefined } — a type so broad it tells you almost nothing.
Data Fetching: TanStack Query
TanStack Query was already in my Next.js projects. Now it's the center of everything.
// Server state that is easy to reason about and debug
const { data: product, isLoading } = useQuery({
queryKey: ['product', productId],
queryFn: () => fetchProduct(productId),
staleTime: 5 * 60 * 1000, // explicit — I chose this
});
// I know exactly what's cached, for how long, and why
// There's no invisible layer making these decisions for me
No mysterious caching behavior. No framework deciding for me what should be fresh and what should be stale. I make those decisions, explicitly, in code I can read.
Forms: TanStack Form
Replaced React Hook Form. Fully type-safe — TypeScript errors if you reference a field that doesn't exist.
const form = useForm({
defaultValues: { email: '', password: '' },
onSubmit: async ({ value }) => {
// value.email is string — not unknown, not any
await loginUser(value);
},
});
<form.Field
name="email" // ← TypeScript error if this field doesn't exist ✅
children={(field) => (
<input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
Build Tool: Vite
Vite is fast, gets out of the way, and just works. It's most of the good parts of Next.js, without the baggage.
Dev server starts in under a second. HMR is instant. Configuration is a single file I can read and understand in five minutes.
Deployment: Anywhere I Want
This one matters more than people talk about.
Next.js is owned by Vercel and while they say it works anywhere, the best experience is on Vercel's platform — that's by design, that's their business model.
TanStack Start uses Vite and Nitro. I deploy to Cloudflare Workers, Railway, Fly.io, a plain VPS — wherever makes sense for the project. No platform lock-in. No vendor dependency.
My hosting costs on the last project dropped significantly when I stopped defaulting to Vercel.
The Moment That Confirmed I Made The Right Choice
Six weeks after switching, I had a bug in production.
A different bug. A real one. State wasn't updating after a form submission.
I found it in eleven minutes.
Not because I'm smarter than I was. Because the code was explicit. I could see where the data was loading. I could see what was happening on the server and what was happening on the client. I could trace the data flow from the database query to the component without hitting invisible framework layers.
Eleven minutes versus four hours.
That's the value of understanding your own code.
The Honest Part — What I Gave Up
I'm not going to pretend this switch had no cost.
React Server Components: TanStack Start does not support RSC yet. If you need RSC specifically — for progressive enhancement or certain performance patterns — Next.js is still the answer.
Ecosystem maturity: Next.js has years of production battle-testing. Authentication patterns, CMS integrations, edge deployment — all established. TanStack Start's patterns are still emerging.
Team hiring: More developers know Next.js. If you're scaling a team, this is a real consideration.
The "safe choice" factor: If something goes wrong with TanStack Start in production, the community is smaller. Fewer Stack Overflow answers. Fewer blog posts. You might be on your own in ways that Next.js users rarely are.
I made this trade consciously. For my use cases, the tradeoffs are worth it.
They might not be for yours.
Should You Switch?
Here's my honest recommendation:
Stay on Next.js if:
- You need React Server Components today
- You're hiring and team familiarity matters
- You're on Vercel and happy there
- Your current projects are running smoothly
Consider TanStack Start if:
- You're building data-heavy apps where type safety matters
- You want to deploy anywhere without a platform dependency
- You've hit the "I don't understand my own framework" wall
- You're starting a new project and want to try something different
Start here regardless:
If you're not using TanStack Query yet — stop reading and install it right now. It's production-stable, works with any React setup, and will immediately make your data fetching code cleaner and more predictable. That's your first step into the TanStack ecosystem, and it requires zero commitment to anything else.
The Bigger Picture
This shift isn't just about replacing one framework with another. It reflects a broader change in what developers value. For years, frameworks have chased automation and abstractions — trying to do more for the developer. But that often came with confusion, slower builds, and less transparency.
TanStack goes the other way. It gives you back control.
That four-hour debugging session changed something in how I think about frameworks. The best tool isn't the one that does the most. It's the one that helps you understand what's happening — so that when things go wrong, you can find the two lines that need to change in eleven minutes instead of four hours.
I stopped using Next.js because I stopped understanding my own code.
I started using TanStack because I wanted that understanding back.
Have you made the switch from Next.js to something else? Or are you firmly staying? I want to hear both sides — especially from teams who've tried TanStack Start in production. Drop your experience in the comments. 👇
Heads up: AI helped me write this.But the debugging incident, the migration experience, and the opinions are all mine — AI just helped me communicate them better. I believe in being transparent about my process! 😊
Top comments (0)