DevPath · Aprende a programar ESPTEN

Producción y despliegue

Configuración: 12-factor y entornos

El problema de la configuración

Un mismo servidor se ejecuta en varios entornos: tu portátil (development), un servidor de pruebas (staging) y producción (production). Cada uno necesita valores distintos: el puerto, la URL de la base de datos, las claves de APIs externas... Si hardcodeas esos valores en el código, mezclas lo que cambia (la config) con lo que no (el programa), y acabas con un if (entorno === "prod") esparcido por todas partes.

La metodología 12-factor

The Twelve-Factor App es un conjunto de buenas prácticas para construir servicios. Su factor III (Config) dice:

Guarda la configuración en el entorno, no en el código.

En concreto:

// En Node, las variables de entorno llegan en process.env (siempre strings).
const PORT = process.env.PORT;          // "3000"
const NODE_ENV = process.env.NODE_ENV;  // "production"

Centralizar y poner valores por defecto

En lugar de leer process.env por todo el código, centraliza la lectura en un único módulo de config que valida y aplica valores por defecto. Así el resto de la aplicación recibe un objeto limpio y tipado:

function cargarConfig(env) {
  return {
    port: Number(env.PORT) || 3000,
    entorno: env.NODE_ENV || "development",
  };
}

const config = cargarConfig(process.env);

En estos ejercicios inyectamos el entorno como un objeto env (en vez de leer process.env directamente). Esto hace la config testeable: puedes probar la misma función con {}, con { PORT: "8080" }, etc.

Separar config por entorno

El valor de NODE_ENV decide el comportamiento: en development quieres logs detallados y mensajes de error completos; en production, logs compactos y errores genéricos (para no filtrar detalles internos). El código es el mismo; solo cambian los valores que recibe.

Gestión de secretos

Las contraseñas, tokens y claves son config especialmente sensible:

Ejemplos

Config centralizada con defaults y validación de secretos

function cargarConfig(env) {
  if (env.NODE_ENV === "production" && !env.DATABASE_URL) {
    throw new Error("Falta DATABASE_URL en producción");
  }
  return {
    port: Number(env.PORT) || 3000,
    entorno: env.NODE_ENV || "development",
    dbUrl: env.DATABASE_URL || "memoria://local",
  };
}

console.log(cargarConfig({ PORT: "8080" }));
console.log(cargarConfig({}));
Pon esto en práctica

DevPath es un curso práctico: aquí lees la teoría; en la app la pones en práctica con ejercicios que se ejecutan de verdad, sin conexión.

Empezar gratis en la app →
Logging y observabilidad →