wandres.dev
DEPLOY · a producción

Post-deploy: operar el sitio en producción

Lo que empieza cuando el despliegue termina: variables de entorno tipadas con astro:env, observabilidad con logs, métricas y trazas, rollbacks para volver a una versión sana, healthchecks que confirman que el sitio responde, y la gestión de dominios con DNS y TLS. Publicar es el comienzo de operar, no el final.

⏱ 16 min

Hay un espejismo peligroso el día que el sitio se publica: creer que el trabajo terminó. En realidad acaba de empezar otro distinto. Un sitio en producción es un sistema vivo que recibe tráfico real, guarda secretos, puede degradarse y a veces hay que devolver a un estado anterior a toda prisa. Operarlo bien exige cinco disciplinas que nada tienen que ver con escribir componentes: gestionar las variables de entorno sin filtrar secretos, montar observabilidad para saber qué pasa dentro, tener rollbacks listos para deshacer un mal despliegue, exponer healthchecks que confirmen que el sitio responde, y administrar el dominio con su DNS y su TLS. Esta lección es sobre lo que ocurre después del despliegue: el oficio silencioso de mantener algo en pie.

🎯 Al terminar esta lección sabrás
  • Gestionar variables de entorno en producción de forma tipada con astro:env.
  • Instrumentar observabilidad con logs, métricas y trazas.
  • Preparar rollbacks y healthchecks para recuperar un sitio sano.
  • Administrar el dominio en producción con su DNS y su certificado TLS.

Variables de entorno en producción

El código es el mismo en todas partes; lo que cambia entre tu máquina y producción son los valores: la URL de la API, la clave de un servicio, el identificador de analítica. Esos valores no se escriben en el código —se inyectan como variables de entorno—, y Astro 7 los gobierna con astro:env, un módulo que los declara con tipo y, sobre todo, con una frontera clara entre lo público y lo secreto.

// astro.config.mjs
import { defineConfig, envField } from 'astro/config';

export default defineConfig({
  env: {
    schema: {
      API_URL: envField.string({ context: 'server', access: 'secret' }),
      PUBLIC_ANALYTICS: envField.string({ context: 'client', access: 'public' }),
    },
  },
});

La distinción context y access es el corazón del sistema. Una variable de context: 'server' y access: 'secret' nunca sale al navegador: vive solo en el runtime, y si por error intentas usarla en el cliente, el build te detiene. Una public sí puede viajar al cliente porque no esconde nada sensible. Consumirlas es una importación tipada, no un acceso a un objeto global sin garantías.

import { API_URL } from 'astro:env/server';
// tipado, validado en el build, e imposible de filtrar al cliente

Las dos dimensiones —context y access— se combinan en un pequeño mapa que conviene tener claro para no filtrar nada por descuido:

  • server mas secret: una clave de API o un token; vive solo en el runtime y jamás llega al navegador.
  • server mas public: un valor no sensible que solo usa el servidor, como una región o un modo.
  • client mas public: un identificador de analítica o una URL pública; puede viajar al cliente sin riesgo.
  • client mas secret: una combinación que no existe, porque un secreto en el cliente ya no es secreto.
⚠️
El secreto vive en la plataforma, nunca en el repositorio

La regla de oro de los secretos en producción: jamás en el código, jamás en el control de versiones. Un fichero .env sirve para desarrollo local y debe estar en .gitignore; los valores reales de producción se configuran en el panel de la plataforma o en el gestor de secretos de tu CI. astro:env te obliga a declarar qué variables existen y de qué tipo son, pero dónde viven sus valores es responsabilidad de la plataforma. Un secreto filtrado en un commit sigue en la historia de git aunque lo borres después: trátalo como comprometido y rótalo de inmediato.

Observabilidad: ver dentro de la caja

Una vez desplegado, tu sitio es una caja que recibe peticiones y devuelve respuestas, y sin instrumentación no tienes ni idea de qué ocurre dentro. La observabilidad son las tres ventanas que abres para verlo, y cada una responde una pregunta distinta.

📜

Logs

El diario de eventos: qué pasó y cuándo. La primera parada cuando algo falla, si registras con intención y no a ciegas.

📊

Métricas

Números agregados en el tiempo: peticiones por segundo, latencia, tasa de errores. Revelan tendencias y disparan alertas.

🧵

Trazas

El recorrido de una petición a través del sistema. Muestran dónde se fue el tiempo cuando algo va lento.

🔔

Alertas

Reglas sobre las métricas que avisan antes de que el usuario se queje. La diferencia entre enterarte tú o que te lo cuenten.

En un sitio estático la observabilidad la aporta casi entera el CDN —códigos de estado, aciertos de caché, ancho de banda—. En SSR se vuelve crítica: cada ruta bajo demanda ejecuta tu código, y necesitas ver sus logs, medir su latencia y saber su tasa de error. La regla práctica es registrar con intención —un log por evento significativo, con contexto suficiente para reconstruir qué pasó— y no ahogar la señal en ruido. Los logs que nadie lee son coste sin valor; los que cuentan una historia son lo primero que agradeces a las tres de la mañana.

Las métricas, además, solo cobran sentido cuando les pones un umbral. Un número aislado —cien milisegundos de latencia— no dice nada; comparado con el objetivo que te fijaste, se vuelve una señal accionable. Definir esos umbrales por adelantado —cuánta latencia toleras, qué tasa de error dispara una alerta— es lo que convierte un panel bonito en un sistema que te avisa antes de que el usuario se queje. Sin umbrales, la observabilidad es decoración; con ellos, es un sentido que se activa solo.

Rollbacks y healthchecks

Por muy buena que sea tu observabilidad, algún despliegue saldrá mal. La pregunta no es si ocurrirá, sino cuánto tardarás en recuperarte, y dos mecanismos definen esa respuesta.

Un healthcheck es un endpoint mínimo que confirma que el sitio está vivo. La plataforma lo consulta a intervalos, y si deja de responder correctamente, sabe que algo se rompió sin esperar a que un usuario lo reporte.

// src/pages/health.ts  -> una ruta bajo demanda que solo dice ok
export const prerender = false;
export const GET = () => new Response('ok', { status: 200 });

Un rollback es volver a la versión anterior cuando la nueva falla. Aquí brilla la disciplina de las lecciones previas: si cada despliegue corresponde a un commit y cada build es un artefacto inmutable, volver atrás es reactivar el artefacto anterior, no reconstruir a la carrera bajo presión. Las plataformas Git-driven lo ofrecen con un clic —promover un despliegue previo— y esa es justamente la recompensa de haber hecho los despliegues reproducibles: el peor momento, el de un fallo en producción, se resuelve con una operación tranquila y ya probada.

Sobre esa base de artefactos inmutables, las plataformas ofrecen estrategias que reducen aún más el riesgo de cada publicación:

  • Despliegue progresivo: la versión nueva recibe primero un porcentaje del tráfico y solo crece si se comporta bien.
  • Azul-verde: dos entornos idénticos conviven, y publicar es apuntar el tráfico de uno al otro, reversible al instante.
  • Inmutabilidad: cada versión conserva su artefacto, así que volver atrás nunca implica reconstruir nada bajo presión.
💡
Un rollback ensayado no es una emergencia

La primera vez que haces un rollback no debería ser durante un incidente real. Practícalo en calma: despliega, promueve una versión anterior, comprueba que el sitio vuelve a su estado previo. Un rollback que ya has ejecutado sin presión deja de ser un salto al vacío y se convierte en un procedimiento aburrido, que es exactamente lo que quieres cuando el sitio está caído y el reloj corre. La capacidad de deshacer, ensayada de antemano, es lo que convierte un incidente en una molestia en lugar de una catástrofe.

Dominios, DNS y TLS

La última milla es la dirección por la que el mundo llega a tu sitio. Un dominio se apunta a tu despliegue mediante registros DNS —un CNAME hacia la plataforma, o un A hacia una IP— y esa propagación tarda un tiempo en verse en toda la red. Sobre el dominio se monta el TLS: el certificado que habilita HTTPS, hoy emitido y renovado de forma automática por casi todas las plataformas, de modo que el candado del navegador no exige gestión manual.

# El patron habitual de DNS para un despliegue moderno:
# raiz     -> registro A o ALIAS hacia la plataforma
# www      -> registro CNAME hacia el destino del proveedor
# el TLS lo emite y renueva la plataforma sin intervencion

Aquí se cierra el círculo con las claves de configuración de Astro: el dominio que apuntas por DNS debe coincidir con el site que declaraste, porque de él dependen el sitemap, las etiquetas canónicas y los enlaces absolutos. Un dominio nuevo sin actualizar site produce un sitio que funciona pero se enlaza a sí mismo con la dirección vieja.

El despliegue de un dominio serio sigue siempre la misma secuencia, y saltarse un paso deja el sitio a medias:

  • Apuntar los registros DNS al destino y esperar a que la propagación se complete en toda la red.
  • Verificar la propiedad del dominio si la plataforma lo exige, para que emita el certificado a tu nombre.
  • Confirmar que el TLS se emitió y que HTTPS responde, y que el tráfico HTTP redirige hacia él.
  • Alinear el site de Astro con el dominio final, para que sitemap y canónicas nombren la dirección buena.
flowchart TD
DEP[nuevo deploy en produccion] --> HC[healthcheck responde ok]
HC --> OBS[logs metricas y trazas]
OBS --> SANO[todo sano la version sigue viva]
OBS --> MAL[error o latencia demasiado alta]
MAL --> RB[rollback a la version previa]
RB --> HC
style DEP fill:#89b4fa,color:#11111b
style RB fill:#f38ba8,color:#11111b
Publicar es un evento, operar es un estado

La cultura del desarrollo celebra el lanzamiento como si fuera la meta —el día del deploy, la captura del sitio en vivo, el mensaje de que ya está publicado—. Pero esa celebración esconde un malentendido sobre la naturaleza de lo que has construido. Un sitio en producción no es un objeto terminado que entregas y olvidas: es un proceso vivo que, a partir de ese instante, existe en el tiempo y hay que sostener en el tiempo. Publicar es un evento, puntual y visible; operar es un estado, continuo y callado. Y todo el andamiaje de esta lección —variables que no filtran secretos, observabilidad que deja ver dentro, rollbacks que deshacen, healthchecks que vigilan, dominios que se sostienen— existe para una sola cosa: que el estado de operar sea aburrido. Porque el objetivo de operar bien no es el heroísmo de apagar incendios a medianoche, sino su ausencia; no la epopeya de recuperar un sitio caído, sino que no se caiga, y que si se cae, volver sea un clic ya ensayado. Esta es quizá la lección más madura de todo el despliegue, la que separa a quien sabe construir de quien sabe sostener: el software no termina cuando compila ni cuando se publica, sino que empieza a vivir justo entonces, y su calidad real no se mide el día del estreno, sino en los mil días silenciosos que vienen después, cuando nadie mira porque todo, sencillamente, sigue funcionando. Construir es hacer que algo exista; operar es hacer que siga existiendo. Y lo segundo es, a la larga, lo que de verdad importa.

⚔️ Prepara tu sitio para vivir en producción
  1. Declara una variable con astro:env marcándola como server y secret, e intenta usarla en el cliente para ver cómo el build te frena.
  2. Añade una ruta health que devuelva ok y configúrala como comprobación de salud en tu plataforma.
  3. Despliega dos versiones y practica un rollback a la anterior sin reconstruir nada, cronometrando cuánto tardas.
  4. Apunta un dominio por DNS, verifica que el TLS se emite solo y confirma que coincide con el site de tu configuración.