Node.js 26 Goes LTS in October. It Already Deleted writeHeader and Six Legacy Stream Modules.
Node.js 26 enters Long-Term Support in October 2026. That's not a headline most solo devs will notice, because LTS transitions are usually boring, a version number moves from "Current" to the recommended default and nothing else changes. This one isn't boring, because 26.0.0 already shipped with real removals back in May, and once it's the LTS default, it's the version every hosting platform, Docker base image, and nvm install --lts command will hand you without asking.
I went through the actual changelog instead of the marketing summary, and there's more here than "new Temporal API, ship it." Some of it will break code that's currently running fine on Node 24 or 22.
What's actually gone
Three removals matter more than the rest:
http.Server.prototype.writeHeader() is fully removed. This was already deprecated for years as an alias for writeHead(), but "deprecated" and "removed" are different words, and I'd bet real money there's still Express middleware and older tutorials floating around that call it directly.
Six legacy stream modules are gone: _stream_wrap, _stream_readable, _stream_writable, _stream_duplex, _stream_transform, and _stream_passthrough. These were internal Node modules that some npm packages imported directly instead of going through the public stream module, because that worked and nobody fixed it. If a dependency three levels deep in your node_modules tree does this, you won't find out from your own code, you'll find out from a stack trace the first time that package's code path actually runs.
--experimental-transform-types is removed as a flag entirely, not just deprecated.
The build-toolchain changes that bite differently
Separate from the runtime removals, the build requirements moved: GCC bumped to 13.2, Python 3.9 support dropped as a build dependency, Windows SDK requirement moved to version 11, and NODE_MODULE_VERSION bumped to 147.
That last one is the sneaky one. Native modules, anything with a compiled .node binary (bcrypt, sharp, sqlite3 builds, a chunk of the sharper end of the npm ecosystem) are tied to that ABI version. A module compiled against Node 24's ABI doesn't just work on Node 26 because the JavaScript looks compatible; it needs to be rebuilt or it fails at require time with a version-mismatch error that looks scarier than the fix actually is.
On the positive side: the Temporal API is on by default now, which is a real upgrade if you've been reaching for date-fns or hand-rolling timezone math because Date is famously bad at it. V8 moved to 14.6, which brings Map.prototype.getOrInsert() and Iterator.concat() as small but genuinely useful additions if you write a lot of data-processing code.
Why "LTS in October" is the actual deadline, not "release in May"
Node 26 has been out since May as the Current release, and if you're the kind of solo dev who tracks Current, none of this is news. Most solo devs don't run Current in production, on purpose, because Current is where the breaking changes land first and LTS is supposed to be the safe, stable target. That's exactly why the October LTS transition is the real deadline: it's the moment this stops being "the bleeding-edge version some people are on" and becomes "the version every new deploy, every fresh Dockerfile FROM node:lts, and every hosting platform's default picks up automatically."
If you've been ignoring Node 26 because it wasn't LTS yet, October is when that stops being a valid reason.
The 20-minute check
Before your next deploy that might land after the LTS switch, or before you next spin up a fresh environment:
node --version npm ls --all 2>&1 | grep -i "gyp\|native" | head -20 grep -r "writeHeader" --include="*.js" --include="*.ts" .
That gives you three things fast: your current version, a rough list of native-module dependencies worth checking for rebuild issues, and any direct writeHeader calls in your own code (it won't catch a dependency's internal use, but it catches the easy case). If your CI runs on a pinned Node version, check that pin. If it doesn't pin at all and just says node: lts, you're going to get 26 automatically the moment LTS flips, whether you tested against it or not.
The honest take
Most solo projects will sail through this with zero changes. If you're not calling writeHeader directly, don't import Node's internal stream modules, and your native dependencies get maintained upstream, this is a non-event for you and the Temporal API is just a nice bonus. The risk is concentrated in exactly two places: older codebases with a few years of accumulated dependencies where nobody's checked what's importing what, and CI/deploy pipelines that don't pin a Node version and will silently pick up 26 the day it becomes the default.
Where I could be wrong: Node's own removal process is usually conservative, and by the time something hits full removal in a numbered release, it's typically been throwing deprecation warnings for two or three major versions. If you've been paying attention to your own DeprecationWarning output in logs, you probably already knew this was coming and this whole post is a non-issue for you.
What I'd actually do
Pin your Node version explicitly in CI and in your Dockerfile right now, regardless of whether you plan to upgrade to 26 this week. That decouples "when I choose to test against Node 26" from "when my infrastructure decides for me," which is the actual risk here, not the removals themselves.
Author
Lukas
@lukcombinator