Introducción
Cuando despliegas una aplicación web creada con IA, el código es solo la mitad de la batalla. La otra mitad es todo aquello con lo que el código se comunica: claves de API de inferencia, cadenas de conexión a bases de datos, credenciales de servicios de terceros y feature flags. Manejarlos mal en producción es la causa más común de caídas reales e incidentes de seguridad reales.
Esta lección cubre el flujo de trabajo práctico para mantener los secretos seguros en tres entornos: desarrollo local, staging y producción. Aprenderás un único modelo mental que funciona tanto si despliegas en Vercel, Railway, Render, Fly.io o en un VPS sin más.
Los tres entornos
Toda aplicación que construyas vive al menos en tres lugares, y cada lugar tiene reglas diferentes para los secretos.
El desarrollo local ocurre en tu portátil. Necesitas iterar rápido, así que los secretos viven en un archivo `.env` que está en gitignore. Los cargas con una librería como `dotenv`. Este archivo nunca se commitea y nunca sale de tu máquina.
Staging es una copia de producción con datos falsos. Existe para detectar errores antes de que los usuarios los vean. Los secretos los inyecta el servicio de hosting (Railway Variables, Vercel Environment Variables, etc.) y están limitados a ese entorno.
Producción es a donde llegan los usuarios reales. Los secretos vienen del mismo servicio de hosting pero viven en un namespace más estricto, a menudo con controles de acceso separados. Una clave de staging filtrada es un fastidio; una clave de producción filtrada es un desastre de facturación.
Cargar variables de entorno en el código
El siguiente patrón funciona para casi cualquier backend en Node.js o Python. La idea clave: leer una sola vez al arrancar, fallar de forma ruidosa si falta un secreto requerido.
Fíjate en la comprobación al arrancar. Es mucho mejor fallar al iniciar que enviar silenciosamente `undefined` a tu cliente de base de datos a las 3 de la mañana. La llamada a `dotenv` solo lee el archivo si existe, lo que significa que el mismo código se ejecuta sin cambios en producción, donde el host inyecta las variables directamente.
En Python, el equivalente usa `pydantic-settings`:
Pydantic lanzará un error de validación claro si falta cualquier campo requerido, logrando el mismo comportamiento de fallo rápido.
Patrones de conexión a bases de datos
Para una base de datos Postgres en un servicio gestionado como Neon, Supabase o Railway, la cadena de conexión es tu secreto. Trátala como una contraseña.
Aquí importan dos cosas. Primero, el pool de conexiones evita que tu aplicación abra una nueva conexión TCP en cada petición. Segundo, SSL es obligatorio en producción. Muchas bases de datos gestionadas rechazan conexiones sin cifrar, pero ser explícito te protege si cambia el comportamiento por defecto.
Para plataformas serverless (Vercel Functions, Cloudflare Workers), usa un pooler de conexiones que resida fuera de la función — Neon trae uno integrado, Supabase tiene el modo de transacción `pgbouncer`. El objeto pool de arriba vive en la memoria del proceso, lo que en serverless significa un pool nuevo por cada cold start, lo cual es lento y puede agotar las conexiones a la base de datos bajo picos de tráfico.
Gestión de claves de API para servicios de IA
Las APIs de IA (OpenAI, Anthropic, Google, etc.) facturan por token. Una clave filtrada puede vaciar una tarjeta de crédito en horas. Tres reglas te mantienen a salvo.
Primero, establece un límite de gasto estricto en el panel del proveedor. Todos los proveedores importantes ofrecen esto. Segundo, crea claves separadas por entorno — `myapp-dev`, `myapp-staging`, `myapp-prod` — para poder revocar una sin tocar las demás. Tercero, nunca registres la clave en logs ni la incluyas en mensajes de error que se envíen a un servicio de logging.
El handler de errores captura el cuerpo de la respuesta para depuración, lo cual está bien porque no contiene la clave — solo el error del proveedor upstream. Si alguna vez necesitas registrar en logs las cabeceras de la petición para depurar, redacta primero el campo `Authorization`.
Errores comunes y cómo evitarlos
El error más frecuente es commitear un archivo `.env`. Aunque sea una sola vez. El historial de Git es para siempre, y los bots escanean GitHub buscando claves expuestas en cuestión de minutos tras un push. Añade `.env` a `.gitignore` desde el primer día y usa herramientas como `git-secrets` o `gitleaks` en CI para bloquear commits accidentales.
El segundo error es usar la misma base de datos para desarrollo y producción. Parece cómodo hasta que un `DROP TABLE` en un script local borra producción. Usa siempre bases de datos separadas, e idealmente proyectos de proveedor separados, para cada entorno.
El tercer error es rotar claves sin un plan. Cuando rotas la contraseña de una base de datos, cada instancia en ejecución de tu aplicación fallará al reconectarse hasta que se reinicie. En plataformas que lo soporten, usa cadenas de conexión que incluyan la contraseña y diseña tu aplicación para reintentar al arrancar. En plataformas como Vercel, un redespliegue tras rotar el secreto lo resuelve automáticamente.
Resumen
Trata cada secreto como si fuera a filtrarse mañana — porque al final lo hará. Usa archivos `.env` en local con `dotenv` o `pydantic-settings`, deja que tu plataforma de hosting inyecte variables en staging y producción, valida los secretos requeridos al arrancar, usa pool de conexiones a la base de datos con `ssl: true` en producción y asigna a cada clave de API de IA un límite de gasto más una clave única por entorno. Esta configuración lleva una tarde montarla y te ahorra la categoría más común de incidentes en producción.
Punto de control de la lección
Repasa lo aprendido y recibe comentarios sobre tu trabajo.