Adamarant
Inizia
Torna agli Appunti

Bun vs Node nel 2026: quando conviene l'uno e quando l'altro

Web Design and Engineering3 set 20267 min di lettura

Bun 1.3 porta un runtime full-stack, Node 24 il TypeScript nativo e un test runner. Usiamo Bun per install e test, Node per il codice che regge il traffico.

Train track switches with yellow levers in daylight

Bun è un runtime JavaScript costruito su JavaScriptCore che tiene dentro lo stesso binario il gestore di pacchetti, il test runner e il bundler, e punta a eseguire senza modifiche il codice scritto per Node. Node è il runtime su cui è stato scritto tutto il registro npm, ed è il default su quasi ogni piattaforma gestita che esegue il codice al posto tuo.

La scelta si presenta in due momenti: quando avvii un servizio nuovo, e quando i tempi di installazione o il conto della CI iniziano a pesare. Nel sondaggio State of JavaScript 2025 il 90% di chi ha risposto dichiara di usare Node e il 21% Bun, in crescita di quattro punti sull'anno precedente, con Deno all'11% (State of JS 2025). Non è una classifica. Quasi tutti i team che usano Bun usano anche Node, in punti diversi dello stesso repository.

La risposta in trenta secondi

Bun va bene dove il lavoro dura poco e la macchina è tua: installazioni, test, script, server di sviluppo locale, utility usa e getta. Node va bene dove il processo resta acceso, è esposto al pubblico e tira dentro pacchetti che non hai scritto tu. Se devi scegliere un solo runtime per un backend SaaS che fra diciotto mesi deve essere ancora in piedi, scegli Node e lascia che Bun si guadagni spazio partendo dalla CI.

Cosa cambia davvero fra Bun e Node

  • Motore. Bun gira su JavaScriptCore, il motore di Safari. Node gira su V8. Cambia il comportamento del garbage collector, cambia il riscaldamento del JIT, cambia il profilo di memoria sotto carico prolungato.
  • Perimetro. Bun è runtime più gestore di pacchetti più test runner più bundler. Node è un runtime che nel frattempo ha aggiunto un test runner e, dalla 24, lo spogliatore dei tipi TypeScript.
  • Direzione della compatibilità. Bun implementa le API di Node. Node non implementa quelle di Bun. Da quando scrivi Bun.serve o bun:sqlite, quel codice gira solo su Bun.
  • Ritmo dei rilasci. Bun pubblica una versione minore quasi ogni settimana. Node pubblica una major ad aprile e una a ottobre, e tiene ogni linea LTS per trenta mesi.
  • Dove esiste come runtime gestito. Node ce l'ha su tutte le piattaforme serverless che contano. Bun ce l'ha su Vercel Functions, in beta pubblica, e su AWS Lambda no.

Dove vince Bun

Installazioni e tempi di CI

È il vantaggio meno discutibile. I benchmark indipendenti del 2026 misurano un'installazione a freddo di un progetto con cinquanta dipendenze sotto il secondo con bun install, contro i circa quattordici secondi di npm; pnpm sta in mezzo e recupera quasi tutto quando la cache della CI è calda (benchmark PkgPulse). Su un monorepo parliamo di minuti risparmiati a ogni esecuzione, per ogni persona del team.

Questo vantaggio lo prendi anche senza adottare Bun come runtime. bun install scrive un lockfile e un node_modules normale, e poi Node esegue il risultato. Se però l'installazione è lenta perché l'albero è enorme, e non perché npm sia lento, il problema sta a monte nella proliferazione delle dipendenze, e un installer più veloce si limita a nasconderlo.

Un binario al posto di quattro strumenti

Un servizio nuovo scritto per Bun non ha bisogno di Jest, né di Vitest, né di tsx, né della configurazione di esbuild. bun test esegue TypeScript direttamente, bun build impacchetta, bun --hot ricarica. La 1.3, uscita in ottobre 2025, ha aggiunto client Postgres, MySQL e Redis integrati, più un server di sviluppo che serve un index.html, risolve i moduli ES e ricarica a caldo senza alcuna configurazione (note di rilascio di Bun 1.3).

Il risparmio si vede nei file di configurazione che non scrivi e che non dovrai aggiornare. Su un servizio interno piccolo vale più di qualunque numero di throughput.

Script e utility locali

Tutto quello che avresti scritto come script di shell con lo shebang di Node sta meglio in Bun. Parte prima, legge TypeScript senza passaggio di build, e ha nella libreria standard gli aiuti per file e comandi di sistema. L'avvio a freddo è il punto in cui il vantaggio di JavaScriptCore si vede di più, e uno script è tutto avvio a freddo.

Throughput grezzo, con un asterisco

Nei benchmark HTTP sintetici Bun stacca Node di parecchio. La 1.3 riporta Express più veloce del 9% e Fastify del 5,4% rispetto alla versione precedente, con un consumo di memoria JavaScript sceso fra il 10 e il 30% (note di rilascio di Bun 1.3). Su un servizio che interroga Postgres a ogni richiesta il runtime raramente è il collo di bottiglia, e la differenza da capo a capo si riduce a qualche punto percentuale. Il throughput va usato per rompere un pareggio, non per motivare la scelta.

Dove vince Node

I moduli nativi

L'ostacolo tipico è il codice nativo: i pacchetti compilati contro la N-API di Node. sharp, bcrypt, better-sqlite3, quasi tutto quello che passa ancora da node-gyp, qualunque cosa distribuisca un binario precompilato per piattaforma. Bun pubblica la copertura delle API di Node modulo per modulo e segna le implementazioni parziali, comprese le riserve sulla N-API (compatibilità Bun con le API di Node.js). Quella pagina va letta contro il tuo albero delle dipendenze prima di decidere, non dopo il primo deploy fallito.

Serverless gestito

I runtime Node gestiti di AWS Lambda coprono la 22, la 24 e la 26, con la 26 arrivata in anteprima pubblica in agosto 2026 (AWS Compute Blog). Un runtime Bun gestito su Lambda non esiste. Vercel invece esegue Bun sulle Functions in beta pubblica, per ora con Next.js, Express, Hono e Nitro (documentazione Vercel): è un passo avanti vero, e resta una beta pubblica per il processo che risponde ai tuoi clienti. Lo stesso ragionamento vale un livello più sotto quando scegli fra edge runtime e Node runtime: il vincolo è cosa la piattaforma gestisce al posto tuo, non cosa va forte in un benchmark sul portatile.

Il divario che Node ha chiuso

Nel 2023 buona parte delle ragioni per passare a Bun era ergonomia, e Node ha passato due anni a smontarle. La 24 esegue node app.ts con lo stripping dei tipi stabile: niente passaggio da tsc, niente cartella di build, nessuna source map da portarsi dietro (documentazione TypeScript di Node.js). Il require() di un modulo ES funziona di default dalla 23 (note di rilascio di Node 23). node --test dà asserzioni, mock, copertura, watch mode ed esecuzione parallela senza installare niente (documentazione di node:test). La 24 è Active LTS con supporto fino ad aprile 2028, e la 26 entra in LTS a ottobre 2026 (rilasci di Node.js).

Lo stripping dei tipi non controlla i tipi: cancella le annotazioni e manda in esecuzione il resto. Quindi tsc --noEmit in CI serve ancora, ed è esattamente il punto in cui il compilatore TypeScript scritto in Go cambia i conti.

Come decidere in dieci minuti

  1. Cerca nell'albero delle dipendenze i pacchetti che portano un file .node o una build node-gyp. Se ne trovi anche solo uno, in produzione va Node.
  2. Guarda dove finisce il codice. Lambda, un'immagine base che non controlli o il cluster di un cliente significano tutti Node.
  3. Cronometra il passo di installazione in CI. Oltre i sessanta secondi, spostalo su Bun questa settimana e lascia stare il runtime.
  4. Cronometra la suite di test. Una run di Jest o Vitest oltre i novanta secondi giustifica una prova con bun test su un branch.
  5. Chiedi chi tiene il telefono di reperibilità. Due anni di chilometraggio in produzione dentro il team battono due settimane, qualunque cosa dica il benchmark.

Cosa usiamo noi e perché

Usiamo Node per tutto ciò che serve traffico e Bun per tutto quello che ci sta intorno. Su Node girano le build Next.js e le route API appoggiate a Supabase, perché è quello che offrono i runtime delle piattaforme e le nostre immagini container, e perché in quegli alberi di dipendenze ci sono moduli nativi. Bun esegue installazioni e test unitari in CI, e fa girare gli script di manutenzione e di contenuto nei nostri repository, dove un avvio da 40ms batte uno da 300ms qualche centinaio di volte al giorno.

A tenere insieme l'impianto è una regola sola: nessuna API esclusiva di Bun dentro il codice applicativo. Niente Bun.serve, niente bun:sqlite, niente Bun.file in qualcosa che potrebbe finire su un server. Scritto così, il runtime sotto un servizio resta una decisione di deploy reversibile in un pomeriggio invece di una riscrittura da mettere in calendario. Il vincolo oggi ci costa quasi niente, ed è la ragione per cui fra un anno la nostra risposta a questa domanda può cambiare senza fare danni.

Foto di pavel ondera su Unsplash

Domande frequenti

Bun è abbastanza stabile per reggere traffico in produzione nel 2026?+

Per un servizio che controlli del tutto, con un albero di dipendenze già verificato sulla pagina di compatibilità Bun con le API di Node, sì. Il rischio non è il runtime che va giù. Il rischio è una dipendenza transitiva compilata contro la N-API, una libreria che si comporta diversamente leggendo process.versions.node, o una piattaforma di hosting senza runtime Bun gestito: tutte e tre saltano fuori tardi. Chi usa Bun in produzione di solito è partito da un servizio solo e ha tenuto Node su tutto il resto per qualche trimestre.

Quanto costa tornare indietro da Bun a Node?+

Quasi niente, se non hai mai importato un modulo bun: e non hai mai chiamato una global di Bun. In quel caso cambi l'immagine base del Dockerfile e il comando in CI, e il codice resta com'è. Diventa caro nel momento in cui Bun.serve è il tuo server HTTP o bun:sqlite è il tuo driver del database, perché ognuna delle due cose è una riscrittura dello strato che tocca ogni richiesta. Quel confine si decide il primo giorno, non durante l'incidente.

Se Node 24 esegue TypeScript nativamente, tsc serve ancora?+

Sì. Lo stripping dei tipi di Node cancella le annotazioni ed esegue quello che resta, quindi un errore di tipo gira tranquillo finché non diventa un errore a runtime. Tieni tsc --noEmit come cancello in CI e usa lo stripping per togliere il passaggio di build dallo sviluppo locale e dagli script. Lo stesso vale per bun run su un file .ts: esecuzione veloce, zero controllo dei tipi.

Dove si colloca Deno in questo confronto?+

Nel sondaggio State of JavaScript 2025 Deno sta all'11%, più o meno la metà di Bun, e risolve un problema diverso: permessi di esecuzione e una libreria standard ripensata da zero, invece della compatibilità con Node a ogni costo. Se guardi oltre Node per avere un modello di esecuzione in sandbox, Deno è il candidato serio. Se lo fai per la velocità di installazione e per avere gli strumenti in un binario solo, Bun è la strada più corta, perché chiede meno al codice che hai già.

Studio

Inizia un progetto.

Scriviamo riguardo a ciò che costruiamo. Raccontaci cosa vuoi costruire tu.