La configuración es el punto donde el software ordenado se encuentra con la realidad desordenada. Elige un formato pensando en quienes lo van a editar, define un único y aburrido orden de precedencia, valida todo al iniciar y niégate a convertir YAML en un lenguaje de programación.
🎙️ Publicado y grabado: · Actualizado ·
Mi regla predeterminada es directa: JSON para datos administrados por máquinas, TOML para ajustes de aplicaciones que mantienen personas, punto env para un límite de despliegue pequeño y YAML solo cuando la herramienta que lo rodea ya lo exige. Los formatos no son adornos intercambiables. Cada uno facilita errores distintos.
# Usa esta tabla de decisión antes de discutir por la sintaxis
lo escribe y lo lee una máquina → JSON
personas mantienen ajustes de la app → TOML
la plataforma inyecta 5–20 cadenas → .env
el ecosistema de herramientas exige YAML → YAML
necesitas condiciones, bucles, imports → usa código, no configuración
JSON tiene una gran virtud: casi todos los lenguajes coinciden en lo que significa. No admite comentarios, las claves requieren comillas dobles y el último elemento no puede llevar coma. No pediría a un equipo de operaciones que mantenga un archivo JSON enorme, pero confío en él como formato de intercambio y artefacto generado.
{
"host": "127.0.0.1",
"port": 8080,
"features": ["search", "billing"]
}
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes. Node suele mostrar SyntaxError: Unexpected token } in JSON at position 42. Corrígelo paso a paso: abre la línea o posición indicada; revisa el elemento inmediatamente anterior a la llave o el corchete de cierre; elimina la coma final; luego ejecuta un analizador, no un formateador, para confirmar que el archivo carga.
YAML parece tranquilo porque desaparece la puntuación. El costo es una estructura invisible. La sangría forma parte de los datos, la mayoría de los analizadores prohíbe las tabulaciones y, según la versión del analizador, palabras sencillas pueden convertirse en booleanos, fechas o números. Pon entre comillas todo lo que deba conservarse como cadena.
service:
host: "127.0.0.1"
port: 8080
mode: "on" # entre comillas: debe seguir siendo la cadena "on"
release: "2026-07-24" # entre comillas: no es un objeto de fecha
code: "0017" # entre comillas: conserva los ceros iniciales
yaml.scanner.ScannerError: mapping values are not allowed here; otros analizadores dicen found character '\t' that cannot start any token. Primero activa la visualización de espacios en blanco en tu editor. Sustituye las tabulaciones por espacios. Después alinea las claves hermanas en la misma columna y vuelve a analizar el archivo. No lo «arregles» agregando espacios al azar hasta que el error se mueva.
Me opongo a usar YAML como lenguaje de programación. Los anchors para repetir un bloque son tolerables. Las plantillas, etiquetas personalizadas, condiciones, interpolación de cadenas y combinaciones de cinco niveles son código con un depurador peor. Si la configuración necesita flujo de control, escribe un pequeño programa con tipos que genere configuración simple y prueba ese programa.
TOML es mi elección cuando las personas son responsables del archivo. Las cadenas parecen cadenas, las secciones son explícitas y los comentarios se conservan. Punto env no es un rival con más funciones. Es una lista práctica de cadenas para el entorno de un proceso. Mantenla plana y pequeña.
# config.toml
[server]
host = "127.0.0.1"
port = 8080
[database]
pool_size = 10
ssl = true
# .env — cada valor entra al proceso como texto
APP_PORT=8080
APP_DEBUG=false
DATABASE_URL=postgresql://localhost/app
APP_DEBUG=false active el modo de depuración. Las variables de entorno son cadenas y, en muchos lenguajes, cualquier cadena no vacía es verdadera. Lee el valor exacto, normaliza mayúsculas y minúsculas, acepta únicamente true o false y rechaza todo lo demás. Nunca lo conviertas con una comprobación genérica de valor verdadero.
Muchos errores de configuración aparecen cuando un valor válido gana desde una fuente inesperada. Elige un orden, publícalo junto a los ajustes y muestra tanto el valor final como su origen. El mío es: primero la opción de línea de comandos; después, el entorno; luego, el archivo local; después, el archivo versionado; y al final, el valor predeterminado de la aplicación.
# gana la prioridad más alta
1. --port 9000 # explícito para esta ejecución
2. APP_PORT=9000 # reemplazo del despliegue
3. config.local.toml # reemplazo local sin versionar
4. config.toml # elección compartida del proyecto
5. default: 8080 # valor de reserva de la aplicación
# salida útil al iniciar
config: server.port=9000 (source: APP_PORT)
Un analizador de configuración solo demuestra que la puntuación es válida. Un esquema demuestra que los valores se pueden usar. Valida tipos, rangos, campos obligatorios, claves desconocidas y relaciones antes de que el servicio acepte tráfico. Fallar al iniciar es más amable que descubrir un tiempo de espera inválido durante la solicitud de un cliente.
# reglas con forma de esquema, independientes de la biblioteca
server.port required integer, 1..65535
server.host required non-empty string
log.level one of: debug, info, warning, error
request_timeout number greater than 0
production forbids debug = true
unknown keys rejected
ConfigurationError: server.port must be between 1 and 65535; got 70000
Additional properties are not allowed ('timout' was unexpected). Corrígelo paso a paso: compara la clave con el esquema; cambia timout por timeout; vuelve a ejecutar la validación; y agrega la escritura incorrecta a un caso de prueba. Ignorar las claves desconocidas convierte un error tipográfico en un misterio de producción.
Haz que los errores del esquema sean concretos. Indica la ruta completa, la restricción esperada y el valor recibido. «Configuración inválida» le ahorra cinco segundos a quien programa y le cuesta media hora a quien opera el sistema.
Un archivo de configuración del repositorio puede indicar qué base de datos usar. No debe contener la contraseña. Guarda los valores secretos en un almacén de secretos del despliegue o en un entorno protegido, incluye en el repositorio un archivo de ejemplo con valores ficticios y deja que la configuración contenga la referencia. Cifrar dentro del mismo repositorio no protege nada si la clave de descifrado está al lado.
# config.toml — se puede versionar
[database]
url_env = "DATABASE_URL"
# .env.example — solo nombres y ejemplos inofensivos
DATABASE_URL=postgresql://user:password@localhost/app
SESSION_SECRET=replace-with-a-random-value
# .gitignore
.env
.env.*
!.env.example
Push cannot contain secrets. No te limites a borrar la línea y volver a intentarlo. Primero revoca o rota la credencial, porque el historial de commits todavía la contiene. Después elimínala del árbol actual y del historial pertinente, sustitúyela por una consulta al entorno, agrega el patrón del archivo a .gitignore y vuelve a ejecutar el detector de secretos.
Si un secreto llegó a un commit, da por hecho que se filtró. Rotarlo es la solución; reescribir el historial es limpieza. Si inviertes esas prioridades, puedes terminar con un repositorio impecable alrededor de una credencial robada que sigue activa.
La configuración pasa más tiempo bajo revisión que durante su escritura. Un orden estable de claves, un elemento por línea, comentarios que expliquen motivos y nada de cambios generados sin sentido permiten ver los errores. Un formato que ahorra tres líneas pero oculta un permiso modificado es un mal negocio.
# fácil de revisar: un cambio semántico produce una diferencia evidente
allowed_origins = [
"https://admin.example.com",
+ "https://reports.example.com",
]
# ruido: la marca de tiempo generada cambia en cada ejecución
-generated_at = "2026-07-23T18:02:11Z"
+generated_at = "2026-07-24T09:41:53Z"
Esta es otra razón para no convertir YAML en un lenguaje de programación. Quien revisa debe ver el valor desplegado en el archivo modificado, no ejecutar mentalmente anchors, plantillas, sustituciones de entorno y condiciones repartidas por cuatro directorios.
Cuando falle la configuración, deja de mirar el archivo que pretendías cargar. Pregúntale al proceso en ejecución qué ruta abrió, qué bytes analizó y qué fuente ganó. Las rutas relativas, los directorios de trabajo, la codificación de texto y los procesos antiguos causan más problemas que los errores exóticos del analizador.
# depura en este orden
1. print the absolute config path
2. confirm that file exists for the running user
3. print a checksum, never secret contents
4. parse it with the same library and version as production
5. validate the schema
6. print resolved keys with source names; redact values
7. confirm whether reload or restart is required
FileNotFoundError: [Errno 2] No such file or directory: 'config.toml'. Muestra el directorio de trabajo del proceso y la ruta absoluta resuelta. Pasa una ruta absoluta desde la definición del servicio o resuélvela en relación con el ejecutable, no con el directorio desde el que alguien inició el proceso. Después verifica los permisos usando la cuenta del servicio.
Unexpected token '', "{..." is not valid JSON. El carácter invisible es una marca de orden de bytes. Inspecciona el archivo como bytes, guárdalo como UTF-8 sin BOM y vuelve a analizarlo. Si los archivos llegan desde una fuente que no controlas, elimina de forma explícita el BOM inicial en el punto de entrada y prueba ese caso.
Conserva este orden de trabajo. Evita la mayoría de los incidentes de configuración y acorta los que queden.
# elegir
JSON datos de máquinas, universal y estricto
TOML ajustes de aplicaciones mantenidos por personas
.env conjunto pequeño de cadenas del despliegue
YAML solo cuando el ecosistema de herramientas lo exige
código condiciones, bucles, imports y cálculos
# analizar con seguridad
JSON comillas dobles; sin comentarios; sin coma final
YAML espacios, nunca tabulaciones; comillas para cadenas ambiguas
TOML secciones poco profundas y nombres explícitos
.env analiza tú los tipos; toda entrada comienza como texto
# precedencia, de mayor a menor
CLI → entorno → archivo local → archivo versionado → valor predeterminado
# contrato de inicio
analizar → rechazar claves desconocidas → validar tipos/rangos → informar origen
# secretos
gestor de secretos / entorno protegido ✓
.env.example con valores ficticios ✓
credencial real en Git ✗
credencial filtrada → rotar primero, limpiar historial después
# depuración
ruta absoluta → permisos → checksum → analizador → esquema → origen
archivo cambiado, app igual → revisar precedencia y comportamiento de recarga
El mejor sistema de configuración es aburrido a propósito. Un formato, una regla de precedencia, un esquema, errores de inicio útiles y ningún valor secreto en el repositorio. Cuando alguien proponga agregar lógica a YAML, di que no y lleva esa lógica a código probado.