Here's a confession. Last week I spent 4 hours deploying a simple blog.
Not a microservices monolith. Not a real-time trading platform. A blog.
I debugged hydration mismatches, fought Edge Middleware configs, and traced why my serverless functions cold-started for 3 seconds on first load. In 2015, I'd FTP the files and be done in 30 seconds.
Where did we go wrong?
The Problem: We Forgot What We Were Solving
Cast your mind back to 2010. PHP ruled the web.
The model was brutally simple:
- Browser requests a page
- Server hits the database, stitches together HTML
- User sees content
Then we said "page reloads are so last decade" and invented SPAs. We moved rendering to the browser, murdered SEO, turned phones into pocket heaters — but achieved buttery smooth transitions.
Fast forward 16 years. Now we're being sold React Server Components.
Let me show you something.
PHP (2010):
<?php
$db = new SQLite3('products.db');
$result = $db->query('SELECT * FROM items');
?>
<ul>
<?php while ($row = $result->fetchArray()): ?>
<li><?= htmlspecialchars($row['name']) ?></li>
<?php endwhile; ?>
</ul>
Next.js RSC (2026):
// app/page.tsx (Server Component)
import { db } from '@/lib/db';
export default async function Page() {
const items = await db.query('SELECT * FROM items');
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
The logic is identical. Server fetches data, renders HTML.
But to run the PHP file, you need any shared hosting for $2/month.
To run the RSC file, you need:
- A Node.js cluster
- CI/CD pipeline
- A build system that separates "server" and "client" bundles
- A serialization layer for props
- Edge runtime configuration (optional but heavily marketed)
We built a launchpad to fly a paper airplane.
Why It Matters: The Numbers Don't Lie
Let's look at the benchmark everyone glosses over. A minimal app that renders <h1>Hello World</h1>.
PHP 8.2:
- Bundle size sent to client: 0 KB (pure HTML)
- Time to Interactive (TTI): ~50ms
- Server memory: ~5 MB per process
Next.js 15, App Router:
- JS bundle: 184 KB (React, React DOM, Next runtime, Webpack runtime)
- TTI on mobile 4G: ~350ms
- Server memory: ~150 MB (Node.js process)
Why should a user download 184 KB of JavaScript to see static text?
The common defense: "It's for future interactivity!"
That's a loan you're taking out on behalf of your user — spending their bandwidth and battery on potential functionality they may never need.
The Request Waterfall
PHP flow:
Client → GET /index.php → Server
Client ← HTML (2 KB) ← Server
[Done. Browser renders.]
RSC flow:
Client → GET /page → Server
Client ← HTML shell (skeleton) ← Server [First paint]
Client → GET /_next/static/chunks/main.js
Client → GET /_next/static/chunks/app/page.js
Client → GET /_next/data/.../page.rsc
Client [Hydration begins...]
[Done. Actually interactive.]
Three extra network round-trips. 200ms of extra latency. On "Hello World."
On a real project, that waterfall becomes Niagara Falls.
The Hydration Trap (And Why RSC Doesn't Fully Escape It)
RSC's biggest selling point: "We eliminated hydration!"
Partially true. Pure Server Components do ship as ready HTML. But the moment you need interactivity — even for a single "Add to Cart" button — you add 'use client'.
Now the server must:
- Render Server Components
- Serialize props for Client Components (pass a function or class instance → serialization error)
- Send HTML + a JSON hydration payload
- Browser downloads React runtime
- Browser downloads client component bundles
- Browser re-executes code to "hydrate" the HTML
Here's the analogy that stuck with me:
Imagine ordering a wardrobe pre-assembled. It arrives at your door, beautiful and ready.
Then a crew shows up and says: "We need to verify the hinges work."
They disassemble the entire wardrobe in your hallway, consult the instruction manual (the JSON payload), and rebuild it from scratch while you watch.
We're literally making computers do the same work twice. First on the server, then on the client.
Efficient? No. Trendy? Absolutely.
The Real Cost of Complexity
Let's talk money. Simple e-commerce scenario.
Classic PHP/Go/Python stack:
- VPS: $5/month
- Database: same server (free)
- Deploy:
git pullor Docker Compose - Total: $5/month. Predictable. Portable.
Next.js on Vercel:
- Vercel Pro (to avoid hitting limits): $20/month
- Cold starts: serverless functions "sleep" — first user after inactivity waits 2-3 seconds
- Vendor lock-in: if your bill hits $1,000/month, migrating off means rewriting half your backend
- Total: $20+/month + engineering hours + lock-in risk
Next.js self-hosted:
- VPS: $5/month (same as PHP)
- You need: a multi-stage Dockerfile, Nginx config for static files, Redis for caching, and 3 hours debugging why
sharpwon't compile on Alpine Linux - Total: $5/month + your weekend
You're not paying for compute. You're paying for architectural complexity.
The Edge Runtime Trap
Vercel heavily markets Edge Middleware and Edge Functions.
"It's faster! Runs on CDN nodes globally!"
What they don't advertise: Edge Runtime is castrated JavaScript. No fs, no standard Node.js APIs. You're in a sandboxed environment that only runs on Vercel (or Cloudflare Workers).
Code written for Edge Runtime won't run in a standard Node.js container on your own VPS.
You're handcuffing yourself to vendor infrastructure by design.
Why We Keep Doing This: Resume-Driven Development
Nobody wants to write in their CV: "Maintained jQuery app, business is happy."
Everyone wants: "Architected micro-frontends on Next.js App Router, migrated to Edge Runtime."
The industry rewards complexity. Simple = junior. Complex = senior.
There's a whole industrial complex built around this. We create problems so we can heroically solve them and negotiate a raise. Business pays for "modern technology" without understanding they're buying air.
When RSC Actually Makes Sense (Be Honest With Yourself)
I'm not anti-progress. Next.js and RSC are powerful tools. But using them for a blog is using a microscope to hammer nails.
You NEED RSC/Next.js if:
- You're building at AirBnB/Vercel scale (hundreds of routes, complex state machines)
- You need Optimistic UI that reacts before the server responds
- You have 50+ frontend developers who need rigid architectural rails to prevent spaghetti
You DON'T need Next.js (use PHP/Go/Python/Astro instead) if:
- You're building a blog or content site (HTML caches better than JSON)
- You're building a B2B admin panel (no SEO needed, a plain Vite SPA is simpler to debug)
- You're a startup with zero budget (a $5 VPS handles 10K users on Go/PHP; Vercel will invoice you during your first traffic spike)
- You're a solo developer or a 3-person team
Key Takeaways
- RSC is server-side rendering — the same pattern PHP has done since 2000, now with a JavaScript build toolchain on top
- The performance overhead is real: 184KB JS bundle vs 0KB, 350ms TTI vs 50ms, 4 network requests vs 1
-
Hydration isn't solved — add one
'use client'component and the full dance resumes - Complexity compounds: what seems manageable in tutorials becomes a DevOps nightmare in production
- Vendor lock-in is a feature for Vercel, not a bug — Edge Runtime code only runs on their infrastructure
- Choose boring technology for boring problems. A blog doesn't need a distributed system.
In 2026, the most radical architectural decision you can make is choosing simplicity on purpose.
Native browser APIs are more powerful than ever — View Transitions API, CSS container queries, the popover attribute. You can build rich, smooth UIs without shipping megabytes of JavaScript.
The best framework is often no framework.
Built something similar? Check out gerus-lab.com
Top comments (0)