Node vs Deno vs Bun: Pick the Support Window, Not the Benchmark
Node publishes end-of-life dates four years out. Deno maintains one LTS line at a time and has already left a two-month gap between two of them. Bun's security policy lists one supported version: 1.x.
Runtime comparisons still open with requests per second, and the number is still mostly irrelevant, because a service that talks to Postgres spends its time waiting on Postgres. There is a question underneath that ages better and takes ten minutes to answer: if you ship this runtime in a container today, how long will somebody publish a security patch for the exact version you shipped?
The three answers are not close to each other. All dates below came off the projects’ own release schedules and security policies on 23 August 2026.
Node publishes dates you can put in a ticket
Node’s release schedule lives in a JSON file in the repository, which means the dates are not a blog post someone has to remember to update. Version 22 ends 30 April 2027. Version 24 entered LTS on 28 October 2025 and ends 30 April 2028. Version 26 shipped 5 May 2026, becomes LTS on 28 October 2026, and ends 30 April 2029. Version 27 is already in the file with an end date of 30 April 2030.
Odd-numbered lines are the trap, and Node 25 is the current example. It started 15 October 2025 and reached end of life on 1 June 2026, about seven and a half months. A base image pinned to node:25 stopped getting security releases in the middle of this year, and nothing about the tag says so.
That predictability is the actual product. Three years of patches on a line you can name in advance is what lets a platform team schedule a runtime upgrade a year out instead of discovering it during an audit.
Deno maintains one LTS line, and it has skipped a month
Deno ships a stable minor every twelve weeks and keeps exactly one long-term support line alive at a time. You get onto it with deno upgrade lts, and backports are limited to security patches and critical bug fixes; API changes and features do not come back.
The history of that channel is short enough to print in full:
| LTS line | Maintenance start | Maintenance end |
|---|---|---|
| v2.1 | 1 Feb 2025 | 30 Apr 2025 |
| v2.2 | 1 May 2025 | 31 Oct 2025 |
| v2.5 | 1 Nov 2025 | 30 Apr 2026 |
| v2.9 | 1 Jul 2026 | 31 Jan 2027 |
Two things fall out of that table. The windows are three to seven months, not three years, so an LTS pin in Deno means moving twice a year rather than never. And there is a gap: the 2.5 line stopped on 30 April 2026 and the 2.9 line did not start until 1 July, leaving two months where the LTS channel had no maintained line under it. If your compliance story is “we run the LTS build,” it is worth knowing that the LTS build can be between lines.
One more detail that bites in Dockerfiles. Deno’s channel is baked into the binary, and a bare version number always resolves to the stable build. Running deno upgrade 2.9.3 on an LTS machine silently moves it to the stable channel, because 2.9.3 exists as two byte-different builds with the same version string. To stay on LTS you upgrade with deno upgrade lts and nothing else.
Bun’s supported version is the newest one
Bun’s SECURITY.md has a supported-versions table with a single row: 1.x.x, checked. There is no end-of-life date anywhere, no LTS channel, and no line that keeps receiving fixes after the next minor lands. Bun 1.3.14 shipped on 13 May 2026; Bun 1.4.0 shipped on 20 August 2026. The patch for anything found today will be in whatever ships next.
For a CLI, a build step, or a test runner in CI, that is fine and arguably correct: you upgrade constantly anyway. For a long-lived service in a regulated shop, “upgrade to the latest minor” is the entire patch process, and it is worth deciding on purpose rather than finding out during an incident.
The other question: whose bug is it when a package breaks
Both challengers publish a per-module compatibility table, and reading the two tables side by side tells you more about their goals than any benchmark does.
Deno marks six node: modules unsupported: cluster, domain, repl, sea, trace_events, and wasi. Their exports are non-functional stubs. Sixteen more, including http, https, net, tls, dns, worker_threads, and zlib, are marked partial. Deno is a runtime with its own web-standard surface that also runs Node code, and the table is where it says which parts it decided not to carry.
Bun marks exactly one module as not implemented, node:sea, and twenty as partial, including child_process, cluster, crypto, tls, and worker_threads. The stated position is stronger than the table: “If a package works in Node.js but doesn’t work in Bun, we consider it a bug in Bun.” That is a promise about triage, not a claim of completeness, and it is the reason Bun’s compatibility has closed as fast as it has.
The practical difference is who does the work when something breaks. On Bun, a compatibility failure is a bug report against the runtime. On Deno, if the module is one of the six, it is not a bug, it is the documented answer, and the work is yours. Neither is worse. They point at different jobs.
What I would actually do with this
If the thing you are choosing a runtime for will still be running in two years, and somebody other than you will have to patch it, Node is the only one of the three that has published a date for the version you would ship, and Node 24 is that version until October, when 26 takes over.
If you want Deno’s permissions model or its TypeScript-without-a-build-step story, take it and put the LTS end date in the calendar with the upgrade already scheduled. Seven months is a real window; it is just not the window most teams assume when they read “LTS.”
If you want Bun, the trade is explicit now: you are choosing a runtime whose patch channel is the release channel. That is a good fit for tooling and CI, where you were going to run the newest version anyway, and a decision that needs a named owner anywhere else.
The check that settles all of this for your own stack is short. Read the version your Dockerfile actually pins, find that version in the project’s schedule or security policy, and see whether a date comes back. For one of these three, no date will.