APIs REST con Node.js, Express y PostgreSQL: Guía de Producción
Lo Que Dominarás en Este Tutorial
- Estructurar aplicaciones Express modulares con capas de controladores, servicios y repositorios
- Configurar connection pooling en PostgreSQL para soportar miles de consultas concurrentes
- Implementar consultas SQL parametrizadas para blindar la base de datos contra inyecciones SQL
- Desplegar en servidores Linux con gestión de procesos PM2 y proxy inverso
import pg from 'pg';
const { Pool } = pg;
export const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // Conexiones concurrentes máximas
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
export async function query(text, params) {
const start = Date.now();
const res = await pool.query(text, params);
const duration = Date.now() - start;
if (duration > 150) {
console.warn(`[CONSULTA LENTA] ${duration}ms: ${text}`);
}
return res;
}
Preguntas Frecuentes
Profundizando: las API REST en producción en la práctica
Los patrones de este tutorial —controladores, servicios y repositorios modulares sobre una conexión a PostgreSQL con pool— son lo que separa una API de demostración de una que sobrevive al tráfico de producción. En la práctica, la configuración del pool es la que hace el trabajo pesado: limitar las conexiones concurrentes, hacer expirar los clientes inactivos y registrar las consultas lentas convierte la base de datos de cuello de botella en un recurso medido. Combinado con consultas parametrizadas en todas partes, el mismo código que soporta una carga de tutorial escala a miles de peticiones concurrentes sin reescribir la arquitectura, y se despliega limpiamente tras un gestor de procesos y un proxy inverso en un servidor sin interfaz gráfica. Nada de esto exige herramientas exóticas: exige disciplina sobre los límites entre capas y respeto por la base de datos como un recurso compartido y finito.
Errores comunes
- Abrir una conexión nueva por petición. Saltarse el pool significa que cada consulta paga el coste de la conexión TCP y la autenticación, y que Postgres alcanza su límite de conexiones con una carga modesta; comparte un único pool configurado en toda la aplicación.
- Construir SQL con concatenación de cadenas. Interpolar la entrada del usuario en las cadenas de consulta es el agujero clásico de inyección SQL; las consultas parametrizadas con marcadores lo neutralizan por completo y mantienen los planes de consulta almacenables en caché.
- Lógica de negocio dentro de los manejadores de ruta. Los controladores gordos que mezclan el análisis de HTTP, la validación, las reglas de negocio y el SQL se vuelven imposibles de probar; mantén los manejadores finos y empuja la lógica a los servicios y repositorios, donde puede probarse por unidades sin HTTP.
- Ignorar los registros de consultas lentas. El envoltorio del pool de este tutorial registra todo lo que supera los 150 ms por una razón: las consultas lentas sin registrar son la forma en que un índice que falta se convierte en silencio en una caída en producción.
Preguntas frecuentes
¿Debería usar un ORM o SQL en bruto para una API seria?
El SQL en bruto con consultas parametrizadas ofrece el máximo rendimiento y planes de consulta transparentes, mientras que los constructores de consultas ligeros añaden seguridad de tipos sin la sobrecarga de un motor: elige según la experiencia del equipo, pero mantén las consultas parametrizadas en cualquier caso.
¿Qué tan grande debería ser mi pool de conexiones?
Parte de la capacidad de tu base de datos, no de tus esperanzas: el pool del tutorial se limita a 20 conexiones concurrentes, y el número correcto es el más pequeño que mantenga los tiempos de respuesta planos bajo tu prueba de carga real, aumentado solo cuando la base de datos —y no la capa de la aplicación— demuestre que tiene margen.
¿Cómo ejecuto esta API en producción?
Despliégala en un servidor en la nube sin interfaz, bajo PM2 para la gestión de procesos y la resistencia a los reinicios, tras un proxy inverso que termine el TLS y reenvíe el tráfico a Express, y con la cadena de conexión a la base de datos en variables de entorno, nunca escrita en el código subido al repositorio.