Someone shipped a modern, commercial web product — user accounts, Stripe payments, a search dashboard, transactional emails — written entirely in C, served over CGI, the technology we all quietly agreed died somewhere around 2004.
Your first instinct is probably to laugh. Or to call it a stunt, a party trick, the kind of thing a certain type of developer does to prove a point on Hacker News. That was my instinct too.
Then I read why he did it, and the laugh died in my throat.
Because every single reason turned out to be a sober, direct answer to a problem I've watched get worse every year I've been doing this. Not nostalgia. Not contrarianism. A clear-eyed response to forces that are reshaping our entire industry right now — supply-chain attacks, AI-generated complexity, and the quietly rising value of software you can actually understand and trust.
The piece that sent me down this hole is Corey Prophitt's "A Modern Web App in C," about his product marketyour.games. I'd encourage you to read his original — this isn't a summary of it. What I want to do is zoom out from his specific build to the thing it's a signal of, because I think the most "insane" stack of 2026 might be pointed directly at the future, and I want to walk through why.
First, no, it's not a toy
Let's kill the easy dismissal upfront, because it's the reason most people stop reading.
This is not a hello-world. It's a real, shipping, commercial product. From the outside it's indistinguishable from anything built on a modern stack: accounts, a dashboard, folders, Stripe, Postmark. From the inside it's C, CGI, SQLite, and OpenBSD — a single statically-linked binary dropped into a folder, three libraries total, deployed by replacing the binary. A clean build takes seconds.
So we're not talking about whether you can do a weekend experiment this way. Someone is taking payments through it. The question isn't feasibility. The question is whether the rest of us have been wrong about something.
Your first objection is probably out of date
The reflexive response is "but CGI is slow — you fork a whole process on every request." And you'd have been completely right to say that. In 2004.
The thing is, that objection quietly expired and nobody re-ran the test. Modern kernels optimize process creation heavily; forking is nowhere near the cost it was when we all fled CGI. And if it ever did become a bottleneck, FastCGI is a small step away. The performance reason we abandoned this entire approach was real then and mostly isn't now — we just never went back to check, because our industry only ever moves in one direction: toward more.
That's the first crack in the certainty. A lot of what we treat as settled fact is really just un-re-examined reflex. "Everyone knows CGI is dead" is doing a lot of load-bearing work for something nobody's actually measured since flip phones were cool.
But performance was never the interesting part. The interesting part is why someone would choose this on purpose today — and those reasons didn't even exist the last time we had this debate.
Why it's not nostalgia: the reasons are brand new
Here's what changed my mind. The case for radical simplicity isn't "the old days were better." It's that three forces, all of them new, all of them intensifying, have quietly made the minimal stack the rational one. And they happen to be the exact forces reshaping everything else about how we build.
Every dependency became a liability
Start with the one I think about most, because I've written about its ugly edges before.
A modern web app's dependency graph is enormous. You add two or three direct dependencies and a package manager cheerfully pulls in hundreds of transitive ones — each maintained by someone you've never heard of, many unmaintained, some with publish credentials protected by a password that's been reused since 2015. That graph is not a convenience. It's your attack surface.
And that attack surface is on fire right now. Package repositories get hit weekly. Attackers register typo-and-hallucination-shaped package names and wait. Autonomous coding agents install dependencies on your behalf, at machine speed, often without a human ever reading what got pulled in. In that environment, every dependency you add is a small act of trust extended to a stranger, multiplied by hundreds, re-rolled every time you update.
Now look at the minimal stack. Its entire supply chain is a C compiler and three libraries — things like libcurl, which the entire internet watches. As Prophitt puts it, compromising it would mean compromising a project under constant global scrutiny, not "a package with eleven weekly downloads and an owner who left in 2019."
"The most secure dependency is the one you never added" used to be a cute aphorism. In 2026 it's a defensive posture. Minimalism stopped being an aesthetic and became a security strategy, and almost nobody has updated their instincts to match.
AI made complexity cheap — which made understanding rare
Here's the second force, and it's the one I find genuinely beautiful.
For the entire history of software, producing code was the expensive, scarce, valuable thing. So we optimized relentlessly for production: frameworks, generators, abstractions, anything that let us make more software faster. Complexity was an acceptable price for output, because output was hard.
AI inverted that overnight. Producing code — even producing abstraction — is now nearly free. You can generate a thousand lines, or a whole framework's worth of scaffolding, in seconds.
And when production becomes free, the bottleneck moves. It moves to understanding and trusting what you now have. The scarce resource isn't the code anymore; it's a human being who can actually hold the system in their head, reason about it, and be confident it does what they think it does. In a world drowning in generated code, a system small enough to comprehend is worth more than it has been in twenty years — because comprehensibility is exactly the thing the flood destroys.
This is why "the whole app fits in your head" stopped being a humblebrag and became a real advantage. A system you can open file by file and fully understand is a system you can verify. And verification, not production, is the hard part now. The minimal stack isn't behind the AI curve. It's weirdly, accidentally, perfectly adapted to it.
The complexity tax finally came due
The third force is just arithmetic catching up with us.
We spent fifteen years adding layers to solve the problems created by the previous layers. The modern default is genuinely strange when you say it plainly: you run a web server (nginx) in front of a second web server (your app server in Ruby, Python, Go), which also happens to hold your business logic. Then you add a container to run it, an orchestrator to run the containers, a build pipeline to produce the containers, and a language server just to help you navigate the abstraction you've accumulated. Each layer solves a real problem — usually a problem the previous layer introduced.
At some point the cure becomes the disease. The minimal stack isn't missing all of that machinery. It never needed it, because it never created the problems the machinery exists to solve. One web server that calls your logic directly. One file to deploy. One language for your editor to understand. The complexity didn't get managed better — it got refused.
What you actually get
Enough philosophy — here's the concrete payoff for a developer weighing whether any of this is more than a thought experiment.
It fits in your head. You can reason about the whole thing, debug it with confidence, and trust it, because there's no layer you haven't seen. Open a file, read it, know what it does. That sounds small until you remember the last time you could say it about anything you shipped.
Less operational tax. No database server to babysit and upgrade. No dependency churn. No upgrade treadmill where half your week goes to keeping the scaffolding standing. Deploying is replacing one binary. The time you don't spend maintaining complexity is time you spend building.
Durable knowledge. HTTP, SQL, processes, the fundamentals — learn them once and they're good for your whole career. Compare that to the framework-of-the-year churn, where the thing you mastered last cycle is a migration guide this cycle. On the minimal stack, what you learn compounds instead of evaporating.
Trivial debugging. Your application is just a program. Pipe it a request, watch what it writes, step through it with a debugger. There's no distributed-systems detective work to figure out which of your seven services ate the request.
The honest counter (because this isn't a cult)
I'd be doing the exact thing I dislike if I only sold you the upside, so here's the fair case against.
You do rebuild things frameworks hand you for free — routing, request parsing, validation, output escaping. That's real upfront work, and real surface area for your own bugs instead of someone else's. It genuinely doesn't fit every problem: large teams moving fast on a shared codebase, deeply interactive rich frontends, extreme scale, or rapid prototyping where ecosystem velocity is the whole point — those are cases where the "bloated" modern stack is earning its keep, not just accumulating.
And C specifically carries a real cost I don't want to wave away: memory safety. A buffer overflow is a worse failure mode than a slow framework. Which is exactly why I'd argue the language is the least important part of this. The thing worth taking seriously is the broader move — radical simplicity, minimal dependencies, a system you can hold whole — and you can reach for most of it in a single-binary Go service, or in Rust, without writing a line of C. The point was never "write C." The point is "stop reaching for maximum complexity by default."
So the honest claim is narrow and, I think, hard to argue with: the pendulum swung much too far toward complexity, most of the old reasons for that swing have quietly expired, and genuinely new forces have made the minimal path far more worth considering than our reflexes allow. Not mandatory. Just no longer insane.
The actual horizon
Here's why I don't think this is going backward, even though it looks like it.
Going backward would be doing the old thing for old reasons — forking processes in 2026 because that's how we did it in 1994, out of habit or sentiment. That's not what's happening. What's happening is a new synthesis: proven, boring, decades-hardened foundations, picked up by people with modern knowledge, for reasons that did not exist when we abandoned them. Supply-chain attacks at this scale are new. AI making production free is new. The premium on verifiable, comprehensible systems is new. The old stack isn't being revived out of nostalgia — it's being rediscovered because it happens to answer questions we only started asking this year.
That's not a retreat. That's the ground moving under you, and realizing the thing you walked away from is now standing on higher ground than where you've been.
The exciting part isn't C, and it isn't CGI. It's the quiet, liberating realization that "modern" was never actually a synonym for "more" — that some of the most resilient, trustworthy, genuinely interesting software of the next few years might come from the people brave enough to subtract. To build something small enough to understand on purpose. To treat every dependency, every layer, every clever abstraction as a cost to be justified rather than a feature to be collected.
Maybe build one small thing you can hold entirely in your head, just to feel what that's like again. I suspect a lot of us have forgotten. And I suspect that feeling — not the next framework — is where the interesting part of the future actually is.
Two honest questions, and I want the real answers. What's the most "outdated" technology you quietly believe is actually better than its shiny replacement for some real use case — and have you been a little embarrassed to admit it? And the harder one: in an age of supply-chain attacks and infinite AI-generated code, is radical simplicity a genuine engineering strategy now, or am I romanticizing a stack because it's elegant? I honestly go back and forth, and I'd rather be argued with than agreed with.