Node.js es el entorno que permitió que JavaScript saliera del navegador y se convirtiera en un lenguaje de servidor de primer nivel. Antes de escribir una sola línea de código conviene entender qué problema resuelve, porque Node.js no es "otro lenguaje más": es una forma concreta de gestionar la concurrencia que explica casi todas sus virtudes y todos sus defectos. Si comprendes su modelo de entrada/salida no bloqueante, el resto del curso deja de ser una colección de recetas y pasa a ser una consecuencia lógica.

En esta lección construiremos esa base conceptual. Usaremos como excusa el proyecto que nos acompañará durante todo el curso: Escena Viva, una pequeña empresa que vende entradas para eventos culturales del Teatro Almendra, la Sala Bóveda y el Auditorio Ribera.

Contenido

  1. Qué es Node.js y qué problema resuelve
  2. JavaScript fuera del navegador
  3. Las piezas conceptuales: V8 y libuv
  4. El modelo de E/S no bloqueante: la analogía del camarero
  5. Comparación con el modelo de un hilo por petición
  6. Para qué es bueno Node.js (y para qué no)
  7. El ecosistema npm y "JavaScript en todas partes"
  8. Versiones LTS y ritmo de publicación
  9. Por qué Escena Viva encaja con Node.js

  1. Qué es Node.js y qué problema resuelve

Node.js es un entorno de ejecución (runtime) de JavaScript del lado del servidor. Dicho de forma más precisa: es un programa que puedes instalar en tu ordenador o en un servidor y que sabe leer ficheros .js y ejecutarlos, dándoles acceso al sistema operativo: ficheros, red, procesos, variables de entorno.

No es un lenguaje. No es un framework. Es el intérprete más las bibliotecas que lo rodean.

El problema histórico que vino a resolver fue el de la concurrencia en servidores web. A finales de los 2000, los servidores tradicionales atendían cada petición con un hilo del sistema operativo dedicado. Un hilo consume memoria (típicamente entre cientos de KB y varios MB de pila) y cambiar de un hilo a otro tiene un coste. Con miles de conexiones simultáneas —muchas de ellas simplemente esperando a que responda una base de datos o a que el cliente termine de descargar— el servidor gastaba la mayor parte de sus recursos en gestionar hilos ociosos.

Este problema tiene nombre propio: el problema C10K (atender diez mil conexiones concurrentes en una sola máquina). La respuesta de Node.js fue radical: un solo hilo para tu código, y todas las operaciones de entrada/salida en modo asíncrono.

Idea central que debes retener: en Node.js, tu código nunca se queda quieto esperando a que termine una operación lenta. Pide la operación, sigue trabajando en otra cosa y, cuando el resultado está listo, vuelve a atenderlo.

  1. JavaScript fuera del navegador

Hasta 2009, JavaScript era prácticamente sinónimo de "el lenguaje de las páginas web". Ryan Dahl tomó el motor V8 de Google Chrome —que ya era muy rápido— y lo empaquetó con una biblioteca de entrada/salida asíncrona. El resultado fue Node.js.

Al sacar JavaScript del navegador cambian las herramientas disponibles:

Concepto En el navegador En Node.js
Objeto global window (o globalThis) global (o globalThis)
Interfaz de usuario document, DOM, eventos de ratón No existe: no hay DOM
Almacenamiento localStorage, IndexedDB Sistema de archivos, bases de datos
Red fetch, XMLHttpRequest (con CORS) fetch, módulos http/https, sockets TCP, sin CORS
Acceso a ficheros Restringido y con permiso del usuario Completo (módulo fs)
Proceso y entorno No accesible process.argv, process.env, process.exit()
Modelo de seguridad Caja de arena (sandbox) del navegador Los permisos del usuario del sistema

Esa última fila es importante: en el navegador, JavaScript vive encerrado por seguridad. En Node.js, tu script puede borrar ficheros, abrir puertos y lanzar procesos. Con esa potencia llega la responsabilidad de no ejecutar código en el que no confías.

Veremos las diferencias en la práctica en la lección Tu Primer Programa en Node.js.

  1. Las piezas conceptuales: V8 y libuv

Node.js se apoya sobre dos componentes principales. Aquí los presentamos a nivel conceptual; la arquitectura detallada y el bucle de eventos con sus fases se estudian en el Módulo 2.

V8: el motor de JavaScript

V8 es el motor de JavaScript desarrollado por Google. Su trabajo es:

  • Analizar (parsear) tu código JavaScript.
  • Compilarlo a código máquina mediante compilación just-in-time, optimizando las funciones que más se ejecutan.
  • Gestionar la memoria con un recolector de basura automático.

Gracias a V8, JavaScript en Node.js no es "un lenguaje interpretado lento": para muchas tareas está a la altura de lenguajes compilados con máquina virtual.

libuv: la biblioteca de E/S asíncrona

V8 sabe ejecutar JavaScript, pero no sabe leer ficheros ni abrir sockets. De eso se encarga libuv, una biblioteca escrita en C que ofrece:

  • Una interfaz uniforme sobre los mecanismos de E/S asíncrona de cada sistema operativo (epoll en Linux, kqueue en macOS/BSD, IOCP en Windows).
  • El bucle de eventos (event loop), que es el motor que reparte el trabajo.
  • Un pool de hilos interno para las operaciones que el sistema operativo no sabe hacer de forma asíncrona (buena parte del acceso a ficheros, compresión, criptografía).
flowchart TB
    A["Tu código JavaScript<br/>(src/catalogo.js)"] --> B["Node.js<br/>APIs: fs, http, path..."]
    B --> C["V8<br/>Ejecuta JavaScript"]
    B --> D["libuv<br/>Bucle de eventos + pool de hilos"]
    D --> E["Sistema operativo<br/>Ficheros, red, temporizadores"]
    C --> D

Una precisión que evita malentendidos frecuentes: cuando se dice que "Node.js es de un solo hilo" se habla del hilo donde se ejecuta tu JavaScript. Por debajo, libuv usa varios hilos. Lo que no ocurre es que dos líneas de tu código se ejecuten a la vez.

  1. El modelo de E/S no bloqueante: la analogía del camarero

Esta analogía es la mejor forma de interiorizar el modelo. Imagina el restaurante del Teatro Almendra en una noche de estreno.

Modelo bloqueante: un camarero por mesa

En un restaurante tradicional, cada mesa tiene su camarero asignado. El camarero:

  1. Toma la comanda de la mesa 1.
  2. La lleva a cocina.
  3. Se queda de pie en la cocina esperando a que el plato esté listo.
  4. Lo lleva a la mesa 1.
  5. Solo entonces atiende a otra mesa.

Para atender 50 mesas necesitas 50 camareros. La mayoría del tiempo están parados esperando a la cocina. Contratar camareros es caro y el pasillo de la cocina se llena de gente que no hace nada.

Modelo no bloqueante: un camarero muy organizado

Ahora imagina un único camarero excepcionalmente eficiente:

  1. Toma la comanda de la mesa 1 y la deja en cocina.
  2. No espera: va a la mesa 2 y toma su comanda.
  3. Va a la mesa 3, sirve las bebidas de la 4, cobra a la 5...
  4. Cuando la cocina toca la campana ("¡pedido de la mesa 1 listo!"), el camarero recoge el plato y lo sirve.

Un solo camarero atiende decenas de mesas, porque el trabajo lento no lo hace él: lo hace la cocina. Él solo coordina.

Traducción a Node.js:

Restaurante Node.js
El camarero El hilo principal donde corre tu JavaScript
Las mesas Las peticiones de los clientes
La cocina El sistema operativo, la base de datos, la red, el disco
La campana de la cocina El evento de "operación completada"
La libreta de comandas pendientes La cola de eventos del bucle
El camarero cocinando él mismo un guiso de 3 horas Un cálculo intensivo de CPU que bloquea todo

Ese último punto es la clave de las limitaciones de Node.js: mientras el camarero cocina, nadie atiende las mesas. Volveremos a ello en el apartado 6.

Cómo se ve esto en código

Fíjate en la diferencia conceptual (no hace falta que entiendas todavía cada detalle; es solo ilustrativo):

// Estilo BLOQUEANTE (síncrono): el programa se detiene en cada línea.
const fs = require('node:fs');

const catalogo = fs.readFileSync('datos/eventos.json', 'utf8'); // Espera aquí
console.log('Catalogo cargado');
console.log('Esta linea se ejecuta despues de leer el fichero');
// Estilo NO BLOQUEANTE (asíncrono): el programa sigue y vuelve luego.
const fs = require('node:fs');

fs.readFile('datos/eventos.json', 'utf8', (error, catalogo) => {
  // Esta función se ejecuta CUANDO el fichero está listo
  console.log('Catalogo cargado');
});

console.log('Esta linea se ejecuta ANTES de que el fichero termine de leerse');

En el segundo caso, la salida por consola aparece en orden "inverso" al que sugiere la lectura del fichero. Eso desconcierta al principio y es exactamente lo que exploraremos a fondo en Callbacks y Programación Asíncrona.

  1. Comparación con el modelo de un hilo por petición

Vamos a comparar Node.js con el modelo clásico que usan (o usaban) PHP con Apache o Java con servlets tradicionales.

Aspecto Un hilo/proceso por petición (PHP clásico, Java tradicional) Node.js (bucle de eventos)
Unidad de concurrencia Hilo o proceso del sistema operativo Callback / promesa en un único hilo
Coste por conexión ociosa Alto (memoria de pila del hilo, ~1 MB o más) Muy bajo (unos pocos KB de estructuras)
Conexiones simultáneas viables Cientos o pocos miles por máquina Decenas de miles por máquina
Modelo mental del programador Sencillo: el código se lee de arriba abajo Requiere pensar en asincronía
Estado compartido en memoria Requiere sincronización (candados, secciones críticas) Sin condiciones de carrera dentro de un callback
Cálculo intensivo de CPU Se reparte entre hilos y núcleos Bloquea a todos los usuarios
Fallo no controlado Suele afectar solo a una petición Puede tumbar todo el proceso si no se gestiona
Aprovechamiento de varios núcleos Automático Requiere cluster o varios procesos (Módulo 10)

No hay un modelo "mejor". Hay un modelo adecuado a un perfil de carga. Node.js brilla cuando el servidor pasa la mayor parte del tiempo esperando a otros sistemas, que es justamente lo que hace una API web moderna.

sequenceDiagram
    participant C1 as Cliente A
    participant C2 as Cliente B
    participant N as Node.js (1 hilo)
    participant BD as Base de datos

    C1->>N: GET /eventos
    N->>BD: consulta eventos
    Note over N: No espera: queda libre
    C2->>N: GET /sesiones
    N->>BD: consulta sesiones
    BD-->>N: resultado eventos
    N-->>C1: respuesta A
    BD-->>N: resultado sesiones
    N-->>C2: respuesta B

  1. Para qué es bueno Node.js (y para qué no)

Casos donde Node.js encaja muy bien

  • APIs REST y microservicios: el trabajo consiste en recibir una petición, consultar una base de datos y devolver JSON. Es E/S casi pura, y JSON es el formato nativo de JavaScript.
  • Aplicaciones en tiempo real: chats, notificaciones, paneles en vivo, seguimiento de aforo. Miles de conexiones abiertas casi siempre ociosas: el escenario ideal.
  • Herramientas de línea de comandos (CLI): arranque rápido, ecosistema enorme, fácil de distribuir con npm. Buena parte del utillaje del desarrollo web moderno está escrito en Node.
  • BFF (Backend For Frontend): una capa fina que agrega llamadas a varios servicios internos y compone la respuesta que necesita exactamente una interfaz. Su trabajo es esperar a varias APIs a la vez: perfecto para Node.
  • Streaming de datos: procesar ficheros grandes o flujos continuos sin cargarlos enteros en memoria (Módulo 3).
  • Prototipado y equipos full-stack: el mismo lenguaje y las mismas validaciones en cliente y servidor.

Casos donde Node.js no es la mejor opción

  • Cálculo intensivo de CPU: procesamiento de vídeo, entrenamiento de modelos, cálculo científico, criptografía masiva, generación de informes con millones de filas en memoria. Mientras tu función calcula, el "camarero" está cocinando y nadie atiende las mesas.
  • Aplicaciones con requisitos estrictos de tipado y concurrencia compleja de memoria compartida, donde otros ecosistemas ofrecen herramientas más maduras.
  • Tareas que exigen precisión numérica decimal, como contabilidad con decimales: el tipo number de JavaScript es de coma flotante. (Por eso, en Escena Viva, guardaremos los precios en céntimos como enteros; lo formalizaremos en la lección El Proyecto del Curso).

Importante: "no es la mejor opción" no significa "imposible". El Módulo 10 muestra cómo sacar el cálculo pesado del hilo principal con worker threads, cómo repartir carga entre núcleos con cluster y cómo diferir trabajo a colas con Redis. La limitación existe, pero tiene soluciones conocidas.

  1. El ecosistema npm y "JavaScript en todas partes"

Junto a Node.js se instala npm (Node Package Manager), el registro de paquetes más grande del mundo, con millones de librerías publicadas. Esto tiene dos caras.

La cara buena: casi cualquier problema común ya está resuelto. ¿Necesitas un framework web? Express. ¿Validar datos? Zod o Joi. ¿Hablar con MongoDB? Mongoose. ¿Generar PDF de una entrada? Hay media docena de opciones.

La cara a vigilar: instalar un paquete es incorporar código de terceros a tu producto. La gestión de dependencias, el versionado semántico y las auditorías de seguridad son parte del oficio, y les dedicamos el Módulo 5 completo.

Además, "JavaScript en todas partes" significa que el mismo lenguaje sirve para el navegador, el servidor, herramientas de compilación, aplicaciones de escritorio (Electron) y funciones sin servidor. Para un equipo pequeño como el de Escena Viva, esto reduce el coste de cambiar de contexto: la persona que valida un formulario en el navegador puede reutilizar esa misma función de validación en la API.

  1. Versiones LTS y ritmo de publicación

Node.js sigue un calendario de publicación muy predecible. Conocerlo evita disgustos en producción.

  • Cada abril sale una versión mayor de número par (20, 22, 24, 26...).
  • Cada octubre sale una versión mayor de número impar (21, 23, 25...).
  • Solo las versiones pares pasan a LTS (Long Term Support, soporte a largo plazo), en octubre del año en que salieron.
  • Las impares son de vida corta (unos seis meses) y sirven para probar novedades.

Ciclo de vida de una versión par:

Fase Duración aproximada Qué recibe ¿Usar en producción?
Current 6 meses (abril → octubre) Todas las novedades Solo para experimentar
Active LTS 12 meses Correcciones y mejoras seguras Sí, recomendado
Maintenance LTS 12 meses Solo correcciones críticas y de seguridad Sí, pero planifica el salto
End of Life — Nada No, sin parches de seguridad

La regla práctica para un proyecto real es simple: usa siempre la última versión Active LTS y planifica la actualización cuando la tuya entre en Maintenance. Para Escena Viva usaremos una versión LTS y la fijaremos en el proyecto para que todo el equipo trabaje igual.

Cómo instalar y cambiar de versión es exactamente el tema de la siguiente lección, Instalación y Configuración del Entorno.

  1. Por qué Escena Viva encaja con Node.js

Escena Viva vende entradas para eventos como el Concierto de Otoño (Teatro Almendra), la Noche de Monólogos (Sala Bóveda) y el Festival de Jazz de Primavera (Auditorio Ribera). Analicemos su carga de trabajo:

Necesidad del negocio Perfil de trabajo ¿Encaja con Node.js?
Catálogo público de eventos y sesiones Leer de base de datos y devolver JSON Sí: E/S pura
Aforo disponible en tiempo real durante una venta anticipada Miles de conexiones abiertas y ociosas Sí: es el caso estrella
Picos de tráfico al abrir la venta de un festival Alta concurrencia, poca CPU por petición Sí
Confirmación de pedido con pasarela de pago externa Esperar respuesta de otra API Sí
Envío de correos con la entrada E/S de red, se puede diferir a una cola Sí (Módulo 10)
Generar 50.000 PDF de entradas de golpe CPU intensiva No en el hilo principal: worker threads o cola
Informe mensual de ventas en CSV Fichero grande Sí, con streams (Módulo 3)

De siete necesidades, seis son E/S. Esa proporción —muy común en aplicaciones de negocio— es la razón por la que Node.js es una elección sensata para esta plataforma. Y la excepción (los PDF) tiene una solución conocida dentro del propio ecosistema.

Este es el aspecto que tendrá, dentro de unos módulos, el punto de entrada de nuestra API. No hace falta que lo entiendas ahora; obsérvalo simplemente como destino:

// Fragmento ilustrativo: NO lo escribas todavía.
// Un servidor mínimo que responde con el catálogo de Escena Viva.
const http = require('node:http');

const servidor = http.createServer((peticion, respuesta) => {
  respuesta.writeHead(200, { 'Content-Type': 'application/json' });
  respuesta.end(JSON.stringify({ mensaje: 'Bienvenido a Escena Viva' }));
});

servidor.listen(3000);

Son ocho líneas para tener un servidor HTTP funcionando, sin instalar nada más. Esa economía de medios también forma parte del atractivo de Node.js.

Errores Comunes y Consejos

Error 1: creer que "un solo hilo" significa "lento" o "no aprovecha el hardware". Un proceso de Node.js con un solo hilo puede atender más conexiones concurrentes que un servidor tradicional con cientos de hilos, porque casi ninguna consume CPU. Y para aprovechar varios núcleos existe cluster (Módulo 10): se lanzan tantos procesos Node como núcleos.

Error 2: confundir "asíncrono" con "paralelo". Asíncrono significa "no espero aquí, me avisan cuando esté". Paralelo significa "dos cosas ocurriendo al mismo tiempo". Node.js hace mucho lo primero y, para tu código JavaScript, nada de lo segundo.

Error 3: pensar que Node.js es un framework web. Node.js sirve para escribir servidores web, pero también CLIs, scripts de automatización, procesadores de ficheros o robots de integración. Express (Módulo 6) es el framework; Node.js es la plataforma.

Error 4: elegir una versión impar para un proyecto serio. Las versiones impares se quedan sin soporte en pocos meses. Si el número mayor es impar, no la lleves a producción.

Consejo 1: piensa siempre en "quién espera". Ante cualquier operación, pregúntate si la espera la hace tu código (mal) o el sistema operativo (bien). Esta pregunta te acompañará todo el curso.

Consejo 2: mide antes de descartar. "Node.js no sirve para cálculo" es cierto a partir de cierta escala. Una operación de 2 ms no bloquea nada apreciable; una de 800 ms sí.

Consejo 3: no memorices APIs, entiende el modelo. Las funciones de fs o de http están documentadas y siempre puedes consultarlas. El modelo de ejecución, en cambio, hay que llevarlo en la cabeza.

Ejercicios

Ejercicio 1: clasificar cargas de trabajo

Para cada una de estas funcionalidades hipotéticas de Escena Viva, indica si es intensiva en E/S o intensiva en CPU, y si Node.js es una buena elección para resolverla en el hilo principal:

  1. Consultar las entradas disponibles del Concierto de Otoño en la base de datos.
  2. Comprimir en un ZIP los 40.000 pases del Festival de Jazz de Primavera.
  3. Mantener abierta una conexión con cada navegador para avisar cuando quedan menos de 20 entradas.
  4. Calcular la asignación óptima de butacas para un grupo de 15 personas en el Auditorio Ribera probando todas las combinaciones.
  5. Llamar a la pasarela de pago para confirmar un cobro.

Ejercicio 2: explicar la analogía con tus palabras

Escribe un párrafo de 5-8 líneas explicando a un compañero que solo conoce PHP por qué un único proceso de Node.js puede atender 10.000 conexiones simultáneas mientras que su servidor Apache se satura a las 300. Debes usar la analogía del camarero y mencionar explícitamente dónde se hace el trabajo lento en cada caso.

Ejercicio 3: decidir una versión

Estás arrancando Escena Viva en agosto de 2026. Consultando el calendario de publicación de Node.js:

  1. ¿Qué línea de versiones elegirías y por qué?
  2. ¿Qué pasará con esa versión aproximadamente dentro de un año?
  3. ¿Qué inconveniente tendría elegir la versión Current recién publicada?

Soluciones

Solución 1

# Funcionalidad Tipo ¿Node.js en el hilo principal?
1 Consultar disponibilidad E/S Sí. El trabajo lo hace la base de datos; Node solo espera el resultado.
2 Comprimir 40.000 pases CPU No. Bloquearía a todos los usuarios durante segundos o minutos. Se resuelve con worker threads o una cola de trabajos (Módulo 10).
3 Conexiones abiertas para avisos E/S Sí, y es el caso donde Node.js más destaca: miles de conexiones ociosas cuestan muy poco.
4 Combinaciones de butacas por fuerza bruta CPU No, si el número de combinaciones es grande. Conviene un algoritmo mejor o sacarlo a un worker.
5 Llamada a la pasarela de pago E/S Sí. Es esperar por la red, exactamente para lo que sirve el modelo asíncrono.

Matiz: el punto 4 depende del tamaño. Si "todas las combinaciones" son unas pocas decenas, el cálculo tarda microsegundos y no hay problema. La pregunta correcta nunca es "¿es CPU?", sino "¿cuánto tiempo bloquea?".

Solución 2 (respuesta modelo)

En Apache con PHP, cada visitante recibe un proceso o hilo propio. Ese hilo pide los datos a MySQL y se queda parado esperando la respuesta, ocupando memoria sin hacer nada útil; como cada hilo cuesta megabytes, a las trescientas conexiones el servidor se queda sin recursos. Node.js funciona como un camarero único muy organizado: toma la comanda (la petición), la deja en la cocina (la base de datos o el sistema operativo) y se va inmediatamente a atender a otra mesa en lugar de esperar de pie. El trabajo lento no lo hace él, lo hace la cocina; él solo coordina y sirve cuando suena la campana. Por eso diez mil conexiones que están casi todo el rato esperando cuestan casi nada: son diez mil comandas anotadas en una libreta, no diez mil camareros. La contrapartida es que, si el camarero se pone a cocinar él mismo un guiso —un cálculo pesado—, todas las mesas se quedan sin atender a la vez.

Solución 3

  1. La última línea par en Active LTS. En agosto de 2026 eso significa la línea 24.x, que entró en LTS en octubre de 2025. Es la que recibe correcciones estables y la que soportan los proveedores de alojamiento y las librerías del ecosistema.
  2. Aproximadamente en octubre de 2027 pasará a Maintenance LTS (solo parches críticos y de seguridad), momento en el que conviene planificar el salto a la siguiente par —la 26.x, que habrá entrado en LTS en octubre de 2026.
  3. La versión Current recién publicada (la 26.x hasta octubre de 2026) trae novedades interesantes, pero puede introducir cambios de comportamiento, muchas librerías nativas aún no la soportan y no está pensada para cargas de producción. Es excelente para probar en local, no para vender entradas.

Conclusión

Node.js es un entorno de ejecución que lleva JavaScript al servidor combinando el motor V8 (que ejecuta el código) con libuv (que gestiona la entrada/salida asíncrona y el bucle de eventos). Su propuesta es sustituir el modelo de "un hilo por petición" por un único hilo que nunca espera: delega el trabajo lento y atiende avisos, como un camarero que coordina en lugar de cocinar.

De ahí se derivan sus fortalezas —APIs, tiempo real, herramientas CLI, capas BFF, streaming— y su debilidad conocida: el cálculo intensivo de CPU bloquea a todo el mundo, algo que el Módulo 10 resuelve con worker threads, cluster y colas. A su alrededor, el ecosistema npm aporta una biblioteca de soluciones inigualable, y el calendario de versiones LTS permite elegir con criterio sobre qué base construir.

Con este mapa mental, hemos visto también por qué Escena Viva —una plataforma de venta de entradas donde casi todo es esperar a bases de datos, pasarelas de pago y clientes— es un caso de uso natural para Node.js.

En la siguiente lección, Instalación y Configuración del Entorno, pasamos de la teoría a la práctica: instalaremos Node.js con un gestor de versiones, verificaremos que todo funciona y crearemos la carpeta escena-viva/ donde vivirá el proyecto durante los doce módulos del curso.

Curso de Node.js: De Principiante a Avanzado

Módulo 1: Introducción a Node.js

Módulo 2: Conceptos Básicos

Módulo 3: Sistema de Archivos y E/S

Módulo 4: HTTP y Servidores Web

Módulo 5: NPM y Gestión de Paquetes

Módulo 6: Framework Express.js

Módulo 7: Bases de Datos y ORMs

Módulo 8: Autenticación y Autorización

Módulo 9: Pruebas y Depuración

Módulo 10: Temas Avanzados

Módulo 11: Despliegue y DevOps

Módulo 12: Proyectos del Mundo Real

© Copyright 2026. Todos los derechos reservados