How JavaScript left the browser and never came back
Ryan Dahl presents Node.js at JSConf EU. Built on Chrome's V8 engine. Event-driven, non-blocking I/O. The idea: JavaScript can do server-side work if you stop making it wait for disk and network. "I want to write servers in JavaScript."
npm (Node Package Manager) ships. The package registry model that changed how JavaScript distributes code. Express.js launches — the web framework that became the default. Socket.io brings real-time to the browser. Heroku adds experimental Node support.
Node.js gets Windows support, opening it to a massive audience. npm 1.0 ships. LinkedIn rewrites its mobile app in Node. Uber follows. The enterprise adoption story begins.
Ryan Dahl steps down as lead. Isaac Schlueter (npm creator) takes over. Node v0.8.0 ships. The project begins its transition from one person's vision to a community-driven effort. Hapi framework launches.
MongoDB + Express + Angular + Node becomes the full-stack JavaScript story. Ghost launches as a Node.js blogging platform. Koa.js (by the Express creators) debuts. PayPal builds Kraken. Node hits the mainstream.
Disagreements over governance and pace of development. A group of core contributors fork Node.js into io.js. Goal: faster releases, open governance, ES6 support. The JavaScript community splits in two.
Node.js and io.js merge under the newly formed Node.js Foundation (Linux Foundation). Node.js 4.0 ships — jumping from v0.12 to v4 to reflect io.js versioning. ES6 support lands. The LTS (Long-Term Support) model is born.
The leftpad incident — a developer unpublished 11 characters from npm, breaking thousands of projects. The npm ecosystem's fragility exposed. Yarn launches as an alternative package manager. Node 6 ships with full ES6 support.
8.8 million Node.js online instances. 3 billion npm downloads per week. 1,500+ contributors. 40,000+ GitHub stars. Node 8 ships with async/await support. The year Node went from "interesting" to "industry standard."
Worker threads land — true parallelism in Node.js. N-API stabilizes (native addon ABI stability). llhttp replaces the HTTP parser. Native crypto improvements. V8 updated to 7.4. Async stack traces arrive.
The Node.js Foundation merges with the JS Foundation to create the OpenJS Foundation. One organization supporting the entire JavaScript ecosystem. npm joins too. Node 12 ships.
Permission model debuts as --experimental-permission. A philosophical shift: Node acknowledges that "trust everything by default" was a design flaw. ES modules gain stability. V8 8.x. Node 14 becomes LTS.
Corepack ships — built-in manager for npm, yarn, and pnpm. packageManager field in package.json. ES modules become the default for new packages. Fetch API lands experimentally. Node 16 becomes LTS.
Fetch API goes stable. node:test — the built-in test runner — ships experimentally. Single executable applications (SEA) announced. Undici becomes the default HTTP client. Node 18 becomes LTS "Hydrogen."
node:test goes stable. Built-in mocking, coverage reporting. Single Executable Applications ship — bundle your Node app into one binary. Permission model picks up traction. Deno 2.0 and Bun 1.0 force Node to innovate faster.
Permission model goes stable in v23.5.0 — --permission flag restricts filesystem, child processes, worker threads by default. Native mocking and coverage in test runner. require(esm) lands — require() can load ES modules.
Single Executable Applications significantly improved. Better native module support, smaller binaries, faster cold starts. Node 24 "Krypton" becomes Active LTS. The runtime now has a real answer to Bun's --compile.
Node 26 ships as the last release under the old odd/even model. Starting with Node 27, every major becomes LTS. One release per year, calendar-aligned, 36 months of support. Node's release model evolves to match the competition.
From Ryan Dahl's laptop in 2009 to the runtime behind most of the web — Node.js's journey is one of community resilience.
The io.js fork could have killed Node. Instead, it forced open governance and made Node stronger. The leftpad incident could have broken trust in npm. Instead, it led to better registry policies. Bun and Deno could have made Node obsolete. Instead, they forced Node to ship built-in test runners, permission models, single executable applications, and a new release cadence.
Node.js's lesson: The ecosystem that survives isn't the one that never breaks — it's the one that breaks and rebuilds stronger. Competition doesn't kill platforms. Complacency does.