A side-by-side experiment

PHP single file
vs JavaScript stack

Same todo app, built twice. Magic-link auth, projects, due dates, five views. Identical UX. One version is 621 lines in a single file. The other is 1,275 lines across five files using Bun, Hono, React 19, Drizzle, Vite, TypeScript, and Tailwind via CDN — the same Tailwind setup as the PHP version. Live: todo-app-php · todo-app-js.

The numbers

Metric PHP JS
Lines of code6211,275
Files (code)15
Dependencies078+ direct (379 in node_modules)
Build time0 s~10 s
Deploy time (from push)~5 s~30–60 s
Docker image size~30 MB~150 MB
Memory at runtime~20 MB~140 MB
First paint1 round-trip3 round-trips
Cold start<100 ms~500 ms

PHP single file

no framework · no build · 1 file

Pros

  • No build step
  • No dependencies
  • Deploy = git pull
  • Iteration: edit → save → refresh
  • Runs on $1/mo shared hosting
  • No npm audit, no supply chain attacks
  • One mental model (1 file)
  • Junior dev gets it in an hour
  • No dependency upgrades that break the app
  • Zero state management bugs (everything in DB)
  • Always fresh data (full reload)
  • SEO friendly out of the box
  • 7× less memory, 5× smaller image
  • Pieter Levels makes $2M+/year this way

Cons

  • No type safety
  • Hard to test (global state, refactor first)
  • Page reload on every action (300–500 ms blink)
  • No optimistic UI
  • Migrations run on every request
  • Without a framework, larger apps fall apart
  • No free API for mobile clients
  • Single-threaded php -S for dev (need php-fpm for prod)
  • Levels.io style has "amateur" reputation
  • Large refactors mean grepping everywhere
  • Hurts past ~3,000 LOC
  • No autocomplete for DB row fields

JavaScript stack

Bun · Hono · React 19 · Drizzle · Vite · TypeScript

Pros

  • Type safety end-to-end (Drizzle generates types from schema)
  • Optimistic UI, drag & drop, animations
  • Real-time features easy (WebSocket, SSE)
  • REST API for free (mobile, browser extensions can consume it)
  • Smooth UX, no page reloads
  • More testable (clear server/client split, pure functions)
  • Migrations run once on boot
  • IDE autocomplete for every DB field
  • Safer large refactors
  • Bun is a fast runtime
  • React has a massive community
  • Same language frontend and backend
  • Scales better for teams

Cons

  • 2× more code for the same functionality (after dropping custom CSS)
  • Build pipeline (Vite, esbuild, plugins) = more things that can break
  • Dep upgrades break things (React 19, Tailwind 4, Vite 7 — all breaking)
  • npm audit + Dependabot maintenance overhead
  • 80+ packages = 80+ maintainers you have to trust
  • 7× more memory
  • 5× larger Docker image
  • Deploy needs build step + container restart
  • 3 round-trips before first paint
  • 8 useState hooks in one component → state bugs
  • HMR sometimes drops, restart the dev server
  • Onboarding a new dev takes hours (Node? Bun? cache?)
  • Shared hosting unusable — VPS minimum
  • SPA has worse SEO without SSR
  • Sometimes fight TS with as or ! to silence the compiler

Why 3 round-trips on JS?

A single-page app can't render the first useful screen until it knows who you are and what to show you. Those two questions are sequential — you can't ask the second until the first returns.

JS waterfall

0 ms GET / → empty <div id="root"></div> shell 50 ms parse HTML, fetch /assets/*.js + *.css 250 ms React mounts, useEffect fires GET /api/auth/me — "who am I?" 350 ms auth resolves, next useEffect fires GET /api/state?view=today — "what should I show?" 450 ms USER SEES UI

PHP timeline

0 ms GET / → server reads session, queries DB, renders full HTML 100 ms USER SEES UI

PHP is fast because the server already knows everything. The browser only has to draw what arrives in the first response. SPAs can match this with SSR + streaming + inline state — but that's hundreds of lines of additional setup that you get for free with server-rendered HTML.

When to pick which

Pick PHP single file when

  • You're a solo developer
  • It's a side project or hobby
  • You want to ship an MVP in a week
  • Indie SaaS with low–mid traffic
  • Internal tools, admin panels
  • Hosting on the cheapest VPS
  • You want to ship today
  • Minimal maintenance for years
  • "Form submit + reload" UX is acceptable

Pick JavaScript stack when

  • Team of 2+ developers
  • Planning a mobile app over the same API
  • Real-time or collaborative features
  • Drag & drop, rich UI interactions
  • App with a 5+ year lifespan
  • UX matters (animations, instant feedback)
  • You have time and energy for the dep tree
The JavaScript stack solves problems most solo projects don't have. PHP single file is a tool proportional to the size of most projects. Pieter Levels isn't right because "PHP is best" — he's right because he picks tools by project size, not by hype.