Every technology choice a small company makes is a bet, and most of them are small enough that being wrong costs a weekend. The choice of runtime is not one of those, since it determines what the code looks like, who can maintain it, how the thing is deployed, and what has to be true in ten years for the software to still start. We made that choice deliberately and we are comfortable saying it out loud, which is that we are building on Bun and the reason is not benchmarks.
The reason is that its API surface is getting wide enough to function as a platform rather than as a runtime, and that a platform with a wide surface owned by one project is a fundamentally different maintenance proposition than an application assembled out of packages, in a direction we think the industry stopped valuing about twenty years ago and is slowly rediscovering.
What the Application Server Actually Gave You
There is a generation of developers who worked with application servers, and there is a generation who only knows the phrase as something slightly embarrassing that older systems used to run on, and I think the second group inherited a caricature rather than an argument. The model had real problems, since deployment units were heavy, startup was slow, configuration was baroque, and the vendors were happy to sell you consulting to explain their own product to you. Those complaints were fair and they are the reason the model lost.
What that model did provide, and what the industry threw away along with it, was a single coherent platform that handled the things every business application needs. Connection pooling was part of the platform rather than a package you chose. Transactions were part of the platform. Scheduling, sessions, security primitives, resource management, and the deployment story were part of the platform, they were versioned together, tested together, documented in one place, and when something misbehaved there was one project responsible for it. You upgraded one thing and the parts moved as a set.
The replacement model, which is the one most of the industry has lived in since, distributes all of that across many small independent projects, each maintained by different people with different priorities, different release schedules, different quality standards, and different appetites for staying interested. The upside was enormous and I do not want to be nostalgic about it, since the freedom to pick a better library than the one the platform shipped is genuinely valuable and the pace of improvement in that period was extraordinary. The cost, which took a decade to become fully visible, is that a business application now depends on several hundred separate decisions by strangers, any one of which can be abandoned, compromised, or rewritten in a way that breaks you.
What Is Actually in the Box Now
The interesting development is not that Bun is fast, since fast is the thing that gets marketed and the least relevant property for the applications we build, where the database is the bottleneck and always was. The interesting development is how much of what an application needs has moved into the runtime itself.
An HTTP server with routing, parameters, wildcards, TLS, cookies, WebSockets, and server metrics is part of the runtime. SQL is part of the runtime, with one Promise based interface covering PostgreSQL, MySQL, and SQLite, which is why we can write queries that work across engines without an abstraction layer sitting between us and the SQL. Password hashing and verification are in the runtime. CSRF token generation and verification are in the runtime. A secrets API, a cron scheduler, an S3 client, a Redis client, TCP and UDP sockets, DNS resolution, file I/O, globbing, streams, workers, child processes, and a shell for scripting are all in the runtime.
And then there is the category that surprised me, because it is the kind of thing nobody expected a runtime to absorb: image decoding, transformation, and encoding; a Markdown parser with GFM extensions; YAML, TOML, JSON5, and JSONL parsing; tar archive creation and extraction; an HTML rewriter that works with CSS selectors. Each of those used to be a package, and in a normal project each of those packages arrived with its own dependency tree, its own release cadence, and its own probability of being abandoned in three years.
Around all of that sits a test runner, a bundler, a transpiler, a package manager with an audit command, and the ability to compile the whole application into a single executable file. That last one matters more than it sounds, because it collapses the deployment story down to copying a file.
This is not a runtime with a good standard library. It is the surface area of a platform, shipped as one binary, versioned as one thing.
Like a System Library, Not Like an Ecosystem
The mental model that fits is the system library rather than the package ecosystem. Nobody installs a package to open a file on a POSIX system, because the operating system provides that, it provides it in a documented and stable form, it has provided it for decades, and the guarantee is the reason an enormous amount of software written a long time ago still compiles. The value is not that the implementation is the best possible one, since a specialized library will usually beat it on some axis, but that it is there, it is the same everywhere, it does not disappear, and everything else in the system was built assuming it.
There is a detail here that people occasionally try to use as a contradiction, which is that the runtime itself is written in Rust while we have written at some length about not using Rust for the applications we build. Both things are correct and they are not in tension, because they describe different jobs. A blacksmith takes a block of steel and turns it into a spoon, working with heat and force and a material that resists him, and the spoon that comes out the other side is then used by somebody to eat soup. You would not hand the diner the block of steel on the grounds that it is the more fundamental object, and you would not ask the blacksmith to shape the metal with a spoon.
The runtime is the block of steel and the forge, so it should be built in a language that gives its authors control over memory, threads, and every cycle, since those authors are solving problems where that control is the entire job. Our applications are the spoon, and they are used by people who need to record an order correctly and go home, so they should be written in a language where the domain rules are legible and a change can be made safely on a Tuesday afternoon. The whole promise of a system library is precisely that the person eating the soup never has to think about the forge.
That is the property we are actually buying. When the HTTP server, the SQL client, the password hashing, the cron scheduler, and the test runner all come from the same project and ship in the same binary, they were built against each other, they were released together, and the interactions between them are somebody's responsibility. In the assembled model, the interaction between your HTTP framework and your database driver and your job scheduler is nobody's responsibility, and the way you discover the seam is in production.
This is what makes zero runtime dependencies possible for us rather than aspirational. We did not achieve it through discipline or asceticism, we achieved it because the runtime got wide enough that the packages became unnecessary, and it is worth being honest that the same commitment would have been unreasonable five years ago.
Single Point of Failure, and Single Point of Repair
The obvious objection to concentrating this much on one project is that it creates a single point of failure, and the objection is correct. I want to accept it fully rather than argue around it, because the interesting part is what sits on the other side of the same coin.
A dependency tree of several hundred packages is not a system without single points of failure, it is a system with several hundred of them, each smaller and each much harder to see. When something in that tree is abandoned, or acquires a maintainer with different intentions, or ships a version with a subtle behavior change, the problem arrives without warning and the diagnosis starts with figuring out which of the hundreds of things moved. The security question has the same shape, since a supply chain attack does not need to compromise the package you chose, it only needs to compromise something six levels underneath it that you have never heard of and never evaluated.
Concentration changes the shape of that risk rather than removing it. There is one changelog to read, one security advisory feed to follow, one upgrade to test, and one project to hold responsible when behavior changes. When something breaks, it breaks in a place we can identify, and the fix arrives as a single version bump rather than as an archaeology project across a dependency graph.
A single point of failure that you can name, upgrade, and file an issue against is a better position than a hundred you cannot enumerate.
There is a second effect that matters for the kind of software we build, which is that the audit surface becomes something a person can actually hold. When a customer in a regulated environment asks what is running inside their operational application, the honest answer being one binary and our own code is a very different conversation from producing a dependency manifest that nobody in the room could meaningfully review.
Where This Bet Can Lose
I would rather write the failure cases myself than have someone else supply them, and they are real.
The largest of them is that a single project means a single organization, and Bun is developed by a company that has investors and therefore has a future that depends on decisions we do not control. The licence is permissive and the source is open, which means the code cannot be taken away, but that protection is thinner than it sounds, because maintaining a JavaScript runtime requires expertise that very few people have and a community fork would need to attract those people quickly. This risk cannot be eliminated by choosing carefully. It can only be accepted or declined.
Then there is blast radius, since a serious vulnerability or a bad regression in a runtime this broad affects everything at once, and there is no partial exposure, no unaffected service, and no comfort of having chosen a different library for that one component. The counterweight is that it is also fixed everywhere at once, but the day it happens is not a comfortable day.
A wide surface is also a wide test surface, and some of it is newer than the rest. We have already published a note about a real problem we hit where Bun's SQL connection pool did not keep the event loop alive in standalone scripts, which is exactly the kind of edge that appears when a platform expands quickly, and it will not be the last one. Choosing this platform means accepting that we will occasionally be the people who find the bug rather than the people who read about it afterward, and that is a real cost in hours that we absorb rather than pass on.
Related to that is API churn, since a surface that is still growing is a surface that occasionally changes shape, and the stability guarantee of a genuinely mature platform is not fully earned yet. Our mitigation is boring and partial, which is to keep our own code thin over the native APIs so that adapting to a change is a small edit in a known place rather than a refactor.
The monoculture argument is the one I take more seriously than the rest, which is that a second independent implementation of a specification tends to make the specification better, and a platform with only one implementation has nothing keeping it honest except its own maintainers. The escape hatch here is genuine but conditional, because the runtime implements both Web standard APIs and a large portion of the Node.js API surface, so ordinary application code moves elsewhere without much drama. What does not move without work is exactly the part we deliberately depend on, which is the native APIs, and that is the price of the strategy rather than an oversight in it.
And there is a smaller practical risk around people, since a developer who has spent years assembling applications from packages sometimes reads a codebase with no dependencies as suspicious rather than as deliberate, and the argument has to be made rather than assumed.
Why We Take It Anyway
The framing that makes this decision look reckless is the one where the alternative is safe, and I do not think that framing survives contact with a real maintenance history. An application assembled from hundreds of packages is not a lower risk position, it is a position where the risk has been divided into pieces small enough that nobody feels responsible for any of them, and where the total exposure is invisible because no one can hold the whole list in their head.
We build software that is expected to run a business for a decade, which means the maintenance is the product and the first release is the cheap part. In that setting, the question is not which arrangement has fewer risks today but which one a competent person can still understand, audit, upgrade, and repair years from now when the original decisions are no longer remembered. One documented platform surface and a codebase of visible application code is an answer to that question. A dependency graph is a deferral of it.
The bet is not that Bun is the best runtime by every measure, and it is not that this decision is permanent. The bet is that the industry spent twenty years dispersing a platform into an ecosystem, that the costs of doing so are now visible to anyone maintaining long-lived software, and that a runtime with the footprint of a system library is where the useful part of the application server was always hiding. The framework we build is a wager on that being true, and so is the generator that builds this site.
If we are wrong, the code is ordinary TypeScript over mostly standard interfaces, and it moves. If we are right, we are maintaining applications a decade from now with one thing to upgrade and one place to look, which is what the platforms that got this shape right the first time were offering before they lost for reasons that had nothing to do with the shape.