Node.js è un runtime JavaScript open source e multipiattaforma che permette di eseguire JavaScript fuori dal browser. Viene utilizzato soprattutto per backend, API, servizi di rete, applicazioni real-time, strumenti da riga di comando e automazioni.

La definizione sembra semplice, ma contiene già il punto che crea più confusione: Node.js non è un linguaggio di programmazione e non è un framework. Il linguaggio resta JavaScript; il runtime è invece l’ambiente che lo esegue e mette a disposizione API per lavorare con rete, file system, processi e altre risorse del sistema operativo.

Il progetto ufficiale lo descrive come un runtime JavaScript asincrono ed event-driven progettato per applicazioni di rete scalabili. Utilizza il motore V8, lo stesso motore JavaScript alla base di Chrome, ma lo porta fuori dal contesto del browser. La documentazione ufficiale è il riferimento primario per questa architettura.

In questa guida vediamo cosa significa davvero, come funzionano event loop e I/O non bloccante, quale ruolo svolgono libuv e i Worker Threads, quando questo modello è una buona scelta e quando invece conviene valutare tecnologie diverse. Alla fine creeremo anche un piccolo server HTTP senza utilizzare framework.

Cos’è e cosa non è Node.js

Node.js è un ambiente di esecuzione per JavaScript. La parola runtime indica proprio questo: un ambiente capace di eseguire il codice e mettere a disposizione funzionalità che il linguaggio, da solo, non possiede.

Se hai già letto la nostra guida su cos’è JavaScript, la distinzione fondamentale è questa:

JavaScript = linguaggio.
Node.js = runtime che esegue JavaScript.

Il browser è a sua volta un ambiente di esecuzione JavaScript, ma mette a disposizione API orientate alle pagine web: DOM, eventi dell’interfaccia, storage del browser e altre Web API.

Il runtime server-side non ha bisogno di una pagina HTML e non dispone normalmente di oggetti browser come document o window. Offre invece API adatte a operazioni come:

  • leggere e scrivere file;
  • aprire connessioni di rete;
  • creare server HTTP;
  • lavorare con processi;
  • eseguire script da terminale;
  • gestire stream;
  • comunicare con servizi e database attraverso librerie e driver.

È quindi lo stesso linguaggio eseguito in un ambiente differente.

Un runtime JavaScript, non un linguaggio né un framework

Definirlo un “linguaggio backend” è impreciso. Il linguaggio è JavaScript.

Anche chiamarlo semplicemente framework è fuorviante. Un framework come Express si installa sopra il runtime e offre astrazioni aggiuntive per routing, middleware e applicazioni web.

La distinzione diventa evidente osservando un semplice programma:

console.log("Ciao da Node.js!");

Salvalo come app.js ed eseguilo dal terminale:

node app.js

Non hai installato un framework e non hai creato un sito. Hai semplicemente chiesto al runtime di eseguire codice JavaScript.

V8 fuori dal browser: cosa cambia davvero

Il motore JavaScript utilizzato è V8, sviluppato nell’ecosistema Chromium. V8 si occupa dell’esecuzione del linguaggio, ma l’ambiente server-side non è soltanto “V8 senza Chrome”.

Attorno al motore esiste un runtime più ampio che aggiunge API, gestione dell’I/O, event loop e integrazione con il sistema operativo.

Questo modello permette a JavaScript di fare cose che nel browser non sarebbero disponibili nello stesso modo. Un programma può, per esempio, leggere un file locale, aprire una porta di rete oppure avviare un processo.

Il modello mentale più utile è quindi:

codice JavaScript → V8 → runtime → sistema operativo / rete / file / processi

Una volta separati questi livelli, anche termini come event loop, callback e I/O asincrono diventano molto meno misteriosi.

Come funziona il runtime

Il tratto più importante dell’architettura è il modo in cui vengono gestite le operazioni che richiedono attesa.

Pensa a una richiesta verso un database, alla lettura di un file o alla comunicazione con un servizio remoto. La CPU non deve necessariamente lavorare per tutto il tempo: spesso deve semplicemente aspettare una risposta.

Bloccare l’intero programma durante quell’attesa sarebbe uno spreco.

Il modello è invece asincrono ed event-driven: il runtime può continuare a gestire altro lavoro mentre alcune operazioni sono in corso.

Event loop e I/O non bloccante

L’event loop coordina l’esecuzione dei callback JavaScript quando il relativo lavoro è pronto.

Consideriamo un esempio semplificato:

console.log("inizio");

setTimeout(() => {
  console.log("timer");
}, 1000);

console.log("fine");

L’output sarà inizialmente:

inizio
fine

e successivamente:

timer

Il programma non rimane fermo per un secondo aspettando il timer.

La stessa idea diventa molto più importante quando l’attesa riguarda rete, file o altri servizi. Il runtime può continuare a gestire eventi e callback invece di dedicare un thread bloccato a ogni singola richiesta.

Questo è uno dei motivi per cui il modello si presta bene a carichi con molte operazioni I/O concorrenti.

Non significa però che qualsiasi applicazione sia automaticamente veloce. Se un callback esegue per molto tempo calcoli sincroni sul thread dell’event loop, le altre richieste devono aspettare.

La documentazione ufficiale insiste infatti sul principio di non bloccare né l’Event Loop né il Worker Pool.

libuv e Worker Pool: il lavoro che non resta sull’Event Loop

Una semplificazione frequente descrive Node.js come “un singolo thread che fa tutto”.

Non è un modello sufficientemente preciso.

Il codice JavaScript ordinario viene coordinato dall’event loop, ma il runtime collabora con il sistema operativo e con libuv, la libreria che contribuisce alla gestione dell’I/O asincrono e del thread pool.

Alcune operazioni possono essere gestite direttamente attraverso meccanismi asincroni del sistema operativo; altre utilizzano un Worker Pool. La documentazione ufficiale cita, tra i casi rilevanti, operazioni relative a file system, DNS, crittografia e compressione.

Il modello è quindi più vicino a:

JavaScript → Event Loop → operazione asincrona → sistema operativo / Worker Pool → completamento → callback

La conseguenza pratica conta più del dettaglio implementativo: non dovresti trasformare l’event loop in una coda bloccata da un singolo lavoro troppo pesante.

Schema del flusso tra Event Loop, operazioni I/O e Worker Pool in Node.js
L’Event Loop coordina l’esecuzione JavaScript, ma non significa che tutto il runtime lavori su un unico thread: alcune operazioni vengono gestite dal sistema operativo o dal Worker Pool.

È davvero single-threaded?

La risposta corretta è: dipende da cosa stai descrivendo.

Dire che l’esecuzione ordinaria del JavaScript avviene sul thread dell’event loop è utile. Dire che l’intero runtime usa sempre e soltanto un thread è invece sbagliato.

Internamente vengono utilizzati altri thread e il modulo worker_threads permette anche di eseguire JavaScript in parallelo.

I Worker Threads sono particolarmente indicati per elaborazioni CPU-intensive. Per il normale I/O, invece, le API asincrone integrate sono generalmente più appropriate. La documentazione di worker_threads classifica questa API come stabile.

Quindi:

  • molte connessioni e molto I/O non richiedono automaticamente molti Worker Threads;
  • un calcolo JavaScript pesante può invece essere candidato a un worker;
  • aggiungere thread non corregge automaticamente un’architettura sbagliata.

A cosa serve nella pratica

Ridurre questa tecnologia alla creazione di “server JavaScript” significa perdere una parte importante dei suoi casi d’uso.

Il runtime viene usato per applicazioni server, ma anche per strumenti di sviluppo, automazioni, command line tool e processi che non espongono affatto un sito web.

Server web, backend e API

Uno degli utilizzi più comuni è l’esecuzione della logica backend di un’applicazione.

Un programma può ricevere richieste HTTP, interrogare un database, applicare regole applicative e restituire una risposta al client.

Se il concetto di client, endpoint, richiesta e risposta non ti è ancora familiare, la nostra guida alle API chiarisce il flusso completo.

Una tipica API potrebbe seguire questo percorso:

client → richiesta HTTP → applicazione → logica → database/servizio → risposta

La risposta viene spesso serializzata in JSON, formato molto diffuso per lo scambio di dati tra applicazioni.

Node.js non è però l’unica tecnologia capace di creare backend o API. PHP, Python, Java, .NET, Go e molti altri ecosistemi possono svolgere lo stesso ruolo. La scelta dipende dal tipo di applicazione, dal team e dai vincoli del progetto.

Applicazioni real-time, WebSocket e streaming

Il modello event-driven è particolarmente interessante quando l’applicazione mantiene molte connessioni o gestisce un flusso continuo di eventi.

Esempi possibili sono:

  • chat;
  • notifiche in tempo reale;
  • dashboard aggiornate continuamente;
  • sistemi collaborativi;
  • gateway e servizi di rete;
  • applicazioni che utilizzano WebSocket;
  • elaborazione di stream.

Il vantaggio non deriva dalla parola “real-time” in sé. Deriva dal fatto che gran parte del lavoro consiste spesso nel ricevere dati, attendere eventi e gestire I/O, anziché mantenere la CPU impegnata in calcoli lunghi per ogni connessione.

Script, automazione, CLI e strumenti di sviluppo

Un file JavaScript può essere eseguito direttamente dal terminale. Questo rende il runtime utile anche per task che non hanno nulla a che vedere con un web server.

Puoi utilizzarlo per:

  • trasformare file;
  • automatizzare attività;
  • generare contenuti o asset;
  • elaborare dati;
  • creare strumenti da riga di comando;
  • eseguire script di build;
  • orchestrare altri processi.

Una parte enorme dell’ecosistema frontend moderno lo utilizza proprio in questo modo: il codice finale può essere destinato al browser, mentre build tool, bundler, generatori e script di sviluppo vengono eseguiti fuori dal browser.

JavaScript e runtime: qual è la differenza

Questa è probabilmente la distinzione da ricordare meglio.

JavaScript è il linguaggio. Node.js è uno degli ambienti in cui quel linguaggio può essere eseguito.

Nel browser JavaScript interagisce soprattutto con la piattaforma Web.

In un runtime server-side interagisce invece con API orientate a file, rete, processi e servizi del sistema operativo.

AspettoBrowserNode.js
LinguaggioJavaScriptJavaScript
AmbienteBrowserRuntime Node.js
DOMDisponibileNon disponibile per default
windowDisponibileNon disponibile per default
File system localeFortemente limitato dal modello browserAPI dedicate
Server HTTPIl browser agisce normalmente da clientPuò crearne uno
Processi di sistemaNon accessibili come in un runtime serverAPI dedicate
ModuliES Modules e piattaforma WebES Modules + CommonJS + moduli integrati

La differenza non sta quindi nella sintassi fondamentale del linguaggio, ma nelle capacità offerte dall’ambiente.

Stesso linguaggio, ambienti e API differenti

Considera questa riga:

document.querySelector("h1");

È JavaScript valido nel browser perché l’ambiente mette a disposizione il DOM (Document Object Model) e quindi l’oggetto document.

In un normale processo Node.js, invece, document non esiste.

Al contrario:

import { readFile } from "node:fs";

utilizza un modulo integrato per interagire con il file system.

Capire questa distinzione evita di attribuire al linguaggio funzionalità che appartengono in realtà all’ambiente di esecuzione.

È frontend o backend?

Node.js viene utilizzato soprattutto nel backend e nel tooling, ma la risposta richiede una precisazione.

Un’applicazione frontend destinata al browser non viene normalmente eseguita “dentro Node.js” quando l’utente visita la pagina.

Il runtime può però essere utilizzato durante lo sviluppo frontend per:

  • eseguire build tool;
  • installare dipendenze;
  • avviare server di sviluppo;
  • compilare o trasformare asset;
  • eseguire test;
  • produrre bundle destinati al browser.

Può inoltre eseguire il backend dello stesso progetto.

Per questo uno sviluppatore JavaScript può lavorare su entrambi i lati utilizzando lo stesso linguaggio, pur operando in ambienti differenti.

npm, package.json e moduli

Un progetto raramente vive soltanto della libreria standard.

L’ecosistema dei pacchetti è una parte fondamentale dell’esperienza di sviluppo, ma anche qui conviene separare alcuni concetti.

Che cos’è npm e cosa installa realmente

npm non è Node.js.

npm comprende un registry di pacchetti, un sito e una Command Line Interface. Il registry pubblico ospita software e metadati, mentre la CLI permette di installare e gestire le dipendenze di un progetto. La documentazione ufficiale npm distingue esplicitamente questi componenti.

Per inizializzare un progetto puoi incontrare il comando:

npm init

o, per accettare rapidamente i valori predefiniti:

npm init -y

Viene creato un file package.json.

Questo file può descrivere, tra le altre cose:

  • nome e versione del progetto;
  • script disponibili;
  • dipendenze;
  • dipendenze di sviluppo;
  • sistema di moduli;
  • altre informazioni utilizzate dagli strumenti.

Quando esegui:

npm install nome-pacchetto

stai aggiungendo una dipendenza al progetto. Non stai “aggiungendo una funzione a JavaScript”: stai incorporando software esterno che il programma potrà importare e utilizzare.

Questa distinzione è importante anche dal punto di vista della sicurezza. Ogni dipendenza introduce codice, versioni e una supply chain che devono essere gestiti.

ES Modules e CommonJS: cosa serve sapere per iniziare

L’ambiente supporta due sistemi di moduli principali:

  • ECMAScript Modules (ESM);
  • CommonJS.

CommonJS utilizza storicamente sintassi come:

const http = require("node:http");

Gli ES Modules utilizzano invece:

import * as http from "node:http";

Gli ES Modules sono supportati pienamente, mentre CommonJS rimane disponibile per compatibilità con l’enorme ecosistema esistente. Il comportamento dei file può essere dichiarato tramite estensioni .mjs e .cjs oppure attraverso il campo "type" di package.json.

La documentazione ufficiale sui package descrive nel dettaglio le regole attuali.

Per un primo esercizio useremo un file .mjs, così la scelta del sistema di moduli resta esplicita.

Quando conviene usarlo e quando scegliere altro

La domanda utile non è “Node.js è migliore di PHP, Python o Java?”.

La domanda utile è:

il suo modello di esecuzione e il suo ecosistema sono adatti al lavoro che deve fare questa applicazione?

I/O, molte connessioni e applicazioni event-driven

Questo modello è particolarmente naturale quando l’applicazione dedica molto tempo ad aspettare operazioni esterne:

  • rete;
  • API;
  • database;
  • file;
  • code;
  • eventi;
  • connessioni persistenti.

In questi scenari l’approccio asincrono può permettere di gestire molto lavoro concorrente senza costruire l’applicazione attorno a un thread dedicato per ogni singola connessione.

Questo non significa che “Node.js scala automaticamente”.

Per scalare servono comunque:

  • codice che non blocchi il runtime;
  • gestione corretta del database;
  • cache quando necessaria;
  • osservabilità;
  • gestione degli errori;
  • architettura dell’infrastruttura;
  • bilanciamento del carico quando richiesto;
  • strategia di deploy.

Il runtime è solo uno dei livelli.

Elaborazioni CPU-intensive e Worker Threads

Un’operazione CPU-intensive mantiene il processore occupato.

Esempi possono essere trasformazioni numeriche pesanti, alcune elaborazioni crittografiche applicative, parsing molto costoso o algoritmi che eseguono grandi quantità di calcoli JavaScript.

Se un task del genere viene eseguito per troppo tempo sul thread dell’event loop, può ritardare la gestione degli altri eventi.

In questi casi puoi:

  • ridurre o ottimizzare il lavoro;
  • spezzarlo quando possibile;
  • spostarlo in un Worker Thread;
  • delegarlo a un processo o servizio specializzato;
  • scegliere un’architettura diversa se il carico dominante è computazionale.

I worker_threads permettono l’esecuzione parallela di JavaScript e sono pensati soprattutto per lavoro CPU-intensive.

Il limite non è quindi “JavaScript server-side non può usare più core”. Il problema reale è evitare che il lavoro sbagliato venga eseguito nel punto sbagliato.

Node.js rispetto a PHP, Python e Java: il criterio corretto

Un confronto sensato deve partire dal progetto.

TecnologiaPunto distintivoHa particolare senso quando
Node.jsJavaScript + modello asincrono/event-drivenbackend I/O-heavy, API, servizi real-time, team JavaScript
PHPecosistema Web e hosting estremamente diffusiCMS, WordPress, applicazioni Web PHP, stack già consolidati
Pythonecosistema molto ampio oltre al Webautomazione, data/AI, servizi Python, backend con framework dedicati
JavaJVM ed ecosistema enterprise maturosistemi enterprise, stack JVM, applicazioni con requisiti organizzativi e architetturali specifici

La tabella non è un benchmark prestazionale. Due applicazioni scritte con tecnologie differenti possono avere risultati completamente diversi in base ad architettura, database, qualità del codice, infrastruttura e carico.

Se stai semplicemente scegliendo una tecnologia perché “Node.js è più veloce”, stai probabilmente partendo dalla domanda sbagliata.

Versioni LTS, Current ed EOL

Il progetto utilizza un ciclo di release in cui le linee possono assumere stati diversi.

I tre termini da conoscere sono:

Current — linea più recente, con le novità introdotte più rapidamente.

LTS — Long Term Support, linea destinata a una finestra di supporto più lunga e normalmente più adatta alla stabilità richiesta dai progetti in produzione.

EOL — End of Life, linea che non riceve più il normale supporto previsto dal progetto.

La pagina ufficiale delle release permette di verificare quali linee sono Current, LTS, Maintenance o EOL. La pagina ufficiale di download propone la release consigliata per l’installazione.

Quale versione installare per un nuovo progetto

Per un progetto destinato alla produzione, la linea LTS corrente è normalmente il punto di partenza più prudente, salvo che dipendenze, provider o requisiti specifici richiedano una versione differente.

La Current ha senso quando vuoi lavorare con le funzionalità più recenti e sei disposto a seguire un ciclo di aggiornamento più rapido.

Non utilizzare invece una versione EOL per iniziare un nuovo progetto senza una ragione tecnica molto specifica: perderesti gli aggiornamenti previsti dal normale ciclo di supporto.

Evita anche di memorizzare un numero di versione letto in una guida. Prima dell’installazione controlla sempre lo stato sulla pagina ufficiale.

Perché conviene usare un version manager

Progetti differenti possono richiedere release diverse.

Un version manager permette di cambiare versione del runtime senza trasformare ogni aggiornamento in una reinstallazione manuale dell’intero ambiente.

È utile soprattutto quando:

  • mantieni progetti vecchi e nuovi;
  • lavori in team;
  • devi riprodurre un ambiente;
  • una dipendenza non è ancora compatibile con la release più recente;
  • vuoi testare un aggiornamento prima di adottarlo.

La cosa importante non è quale version manager utilizzi, ma rendere esplicita e riproducibile la versione richiesta dal progetto.

Installazione e verifica dal terminale

Per una prima installazione, usa la pagina ufficiale di download e scegli una modalità adatta al tuo sistema operativo.

Per un progetto normale partirei dalla release LTS corrente, a meno che tu non abbia un requisito preciso per la Current.

Evita download provenienti da siti casuali: per binari e documentazione è preferibile partire dalle fonti ufficiali.

Verificare runtime e npm

Dopo l’installazione apri il terminale e digita:

node --version

oppure:

node -v

Se tutto è installato correttamente vedrai la versione disponibile.

Controlla poi npm:

npm --version

Non serve che il numero npm coincida con quello del runtime: sono componenti distinti con versioning differente.

Puoi infine creare app.js:

console.log("Node.js funziona");

ed eseguire:

node app.js

Se il terminale stampa:

Node.js funziona

hai già eseguito il tuo primo programma JavaScript fuori dal browser.

Primo esempio: un server HTTP senza framework

Per capire la differenza tra runtime e framework conviene evitare, almeno nel primo esempio, Express.

La libreria standard include già un modulo HTTP capace di creare client e server. La relativa API fa parte del core ed è documentata nella sezione ufficiale dedicata al modulo HTTP.

Crea un file chiamato:

server.mjs

e inserisci:

import { createServer } from "node:http";

const hostname = "127.0.0.1";
const port = 3000;

const server = createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain; charset=utf-8");
  res.end("Ciao da Node.js!");
});

server.listen(port, hostname, () => {
  console.log(`Server attivo su http://${hostname}:${port}/`);
});

Avvialo:

node server.mjs

Vedrai un messaggio simile a:

Server attivo su http://127.0.0.1:3000/

Apri quell’indirizzo nel browser e riceverai:

Ciao da Node.js!

Non abbiamo usato Express, Apache o NGINX per creare questo esempio. Il server HTTP è stato aperto direttamente attraverso un modulo integrato.

Questo aiuta anche a distinguere il runtime dal concetto generale di server: un server è un ruolo o un software che fornisce un servizio; Node.js è invece l’ambiente con cui puoi creare un’applicazione capace di svolgere quel ruolo.

Cosa succede quando arriva una richiesta

La chiamata:

createServer((req, res) => {

crea un server e registra una funzione che verrà eseguita quando arriva una richiesta.

req rappresenta la richiesta ricevuta.

res rappresenta la risposta che costruiremo.

Con:

res.statusCode = 200;

indichiamo un esito positivo.

Con:

res.setHeader("Content-Type", "text/plain; charset=utf-8");

dichiariamo il tipo di contenuto.

Infine:

res.end("Ciao da Node.js!");

invia il corpo della risposta e la conclude.

È un esempio volutamente minimale, ma contiene già il meccanismo centrale di molte applicazioni di rete:

richiesta → callback → logica → risposta

In un’applicazione reale aggiungeresti routing, validazione, accesso ai dati, autenticazione, logging, gestione degli errori e altri livelli.

Express non è il runtime

Una delle confusioni più frequenti nasce perché molti tutorial iniziano direttamente con Express.

Express è un framework Web per Node.js. Node.js è il runtime che lo esegue.

Il sito ufficiale di Express lo definisce un framework Web minimalista e flessibile.

La libreria standard possiede già API HTTP native. Express aggiunge però astrazioni comode per attività come:

  • routing;
  • middleware;
  • gestione delle richieste;
  • gestione delle risposte;
  • organizzazione dell’applicazione.

Con le API native puoi creare un server HTTP.

Con Express puoi costruire sopra il runtime un’applicazione Web utilizzando convenzioni e API di livello più alto.

La relazione può essere sintetizzata così:

JavaScript → Node.js → Express → applicazione

Non devi quindi “scegliere tra Node.js ed Express” come se fossero alternative dello stesso livello.

La vera scelta è se utilizzare direttamente le API del runtime oppure adottare Express o un altro framework che aggiunga un livello di astrazione.

Domande frequenti

Node.js è gratuito e open source?

Sì. Node.js è un progetto open source e multipiattaforma. Può essere eseguito sui principali sistemi operativi e progetto, documentazione e release sono disponibili attraverso i canali ufficiali.

Questo non significa però che tutti i servizi, hosting, database o pacchetti utilizzati insieme al runtime siano necessariamente gratuiti o open source.

Node.js è un web server?

Non esattamente.

Node.js è un runtime JavaScript. Tra le API integrate contiene strumenti che permettono di creare un server HTTP, quindi un’applicazione eseguita in questo ambiente può svolgere il ruolo di server.

Chiamare l’intero runtime semplicemente “web server” nasconde però gran parte delle sue funzioni: può eseguire CLI, script, automazioni, processi di build e programmi che non ascoltano alcuna porta HTTP.

Bisogna conoscere JavaScript prima di Node.js?

È fortemente consigliato.

Il runtime non sostituisce le basi del linguaggio.

Prima di affrontarlo dovresti almeno comprendere:

  • variabili;
  • funzioni;
  • array e oggetti;
  • scope;
  • moduli;
  • Promise;
  • async e await;
  • gestione degli errori.

Senza queste fondamenta rischi di attribuire all’ambiente di esecuzione problemi che dipendono invece dal funzionamento di JavaScript.

Node.js può eseguire TypeScript?

Sì, ma bisogna distinguere supporto leggero nativo e toolchain TypeScript completa.

Le versioni moderne possono eseguire direttamente una parte del codice TypeScript attraverso il type stripping, cioè rimuovendo la sintassi dei tipi che non necessita di trasformazione in JavaScript.

Non significa però che il runtime sostituisca automaticamente il compilatore TypeScript.

Il supporto integrato:

  • non esegue type checking;
  • non interpreta automaticamente tutte le funzionalità che richiedono trasformazione;
  • non applica l’intera configurazione di tsconfig.json;
  • non sostituisce una toolchain completa quando il progetto ne ha bisogno.

La documentazione TypeScript ufficiale distingue infatti il type stripping nativo dall’esecuzione con strumenti esterni quando serve supporto completo.

Conclusione

Node.js diventa molto più semplice da capire quando smetti di considerarlo un generico “framework per fare backend”.

È un runtime che esegue JavaScript fuori dal browser e mette a disposizione un ambiente progettato attorno a I/O asincrono, eventi e applicazioni di rete.

Questo modello lo rende particolarmente adatto a backend, API, servizi real-time, automazioni e applicazioni che devono gestire molte operazioni concorrenti senza trascorrere la maggior parte del tempo in calcoli CPU pesanti.

Il punto più importante, però, è evitare gli slogan.

Non è automaticamente più veloce di qualsiasi altra tecnologia, non utilizza letteralmente un solo thread per tutto e non coincide con Express, npm o JavaScript.

Se devi decidere se adottarlo in un progetto, parti dal carico reale: molto I/O, eventi e un team già competente in JavaScript sono segnali favorevoli; carichi computazionali dominanti o un ecosistema consolidato su un’altra tecnologia possono portare a una scelta diversa.

Una volta chiarito questo, il passo successivo non è installare dieci framework. È costruire un piccolo progetto, osservare come si comportano richieste asincrone, errori e callback e imparare a riconoscere ciò che può bloccare l’event loop.