Saltar al contenido
← Volver al blog
infraestructuraseguridad

Variables de entorno: producción, preview y local

En qué se diferencian las variables de entorno de producción, preview y local en Vercel y Netlify, qué valor va en cada una y los errores que filtran claves.

Por Equipo Devonauts5 min de lectura
Read in English →
La pantalla de una laptop, vista de costado, muestra un depurador con el panel Threads and Variables

Las variables de entorno de producción, de preview y locales son tres listas separadas: producción es lo que usa tu sitio en vivo, preview es lo que usan los builds de ramas y pull requests, y local vive en un archivo en tu computadora. Una variable cargada en una lista no existe en las otras, un cambio solo se aplica en el siguiente despliegue, y todo lo que lleva un prefijo público como VITE_ o NEXT_PUBLIC_ queda grabado en el código del navegador al compilar.

En esta guía te explicamos cómo funcionan los tres entornos en Vercel y Netlify, qué valores van en cada uno en una app típica con Supabase y Stripe, y cómo comprobar qué está usando de verdad un despliegue.

¿En qué se diferencian los tres entornos?

ProducciónPreviewLocal
Lo usaTu dominio en vivoLos despliegues de ramas y pull requestsTu computadora cuando corres el servidor de desarrollo
Nombre en VercelProductionPreview (todas las ramas o una en particular)Development, se descarga con vercel env pull
Nombre en NetlifyProductionDeploy Previews y Branch deploysLocal development (Netlify CLI)
Dónde se guardaPanel del hostingPanel del hostingUn archivo como .env.local que nunca se sube al repositorio
¿Debe ver datos reales de clientes?SíNoNo

Vercel también admite entornos personalizados, y las dos plataformas permiten sobrescribir un valor de preview para una rama concreta. En Vercel, el valor específico de una rama reemplaza al valor general de preview con el mismo nombre, así que solo agregas los que cambian.

¿Qué valor va en cada entorno?

En una configuración común (frontend en Vercel o Netlify, Supabase para datos e inicio de sesión, Stripe para pagos), un reparto sensato es este:

VariableProducciónPreviewLocal
VITE_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_URLProyecto de producciónProyecto de pruebasPruebas o una instancia local
Clave anon o publishable de SupabaseLa de producciónLa de pruebasLa de pruebas
Clave service role o secret de SupabaseSolo en funciones del servidorLa de pruebas, solo servidorLa de pruebas, solo servidor
Clave secreta de StripeModo live (sk_live_…)Modo de prueba (sk_test_…)Modo de prueba
Secreto de firma del webhook de StripeEl del endpoint liveEl del endpoint de pruebaEl que da la Stripe CLI
URL del sitio para correos y redireccioneshttps://tuapp.comLa URL del preview o el dominio de pruebashttp://localhost:5173 o similar

La idea central: los builds de preview nunca deberían tocar datos de producción ni cobrar tarjetas reales. Si todavía no tienes una base de datos de pruebas, la guía de entorno de pruebas (staging) muestra la forma más barata de sumarla.

¿Qué variables se ven en el navegador?

Los frameworks de frontend solo exponen las variables con prefijo público. En Vite es VITE_; en Next.js, NEXT_PUBLIC_. Se reemplazan por su valor literal al compilar la app, así que cualquiera puede leerlas en las herramientas de desarrollo del navegador. La documentación de Vite es clara: las variables VITE_ no deben contener información sensible como claves de API.

De ahí sale una regla simple:

  • Pueden ser públicas: la URL de Supabase, la clave anon o publishable de Supabase (siempre que Row Level Security proteja tus tablas), la clave publicable de Stripe, los ID de analítica.
  • Nunca públicas: la clave service role o secret de Supabase, las claves secretas de Stripe, las claves de OpenAI u otras APIs de IA, los secretos de webhooks, las contraseñas de bases de datos.

Si una herramienta de IA escribió VITE_OPENAI_API_KEY o NEXT_PUBLIC_STRIPE_SECRET_KEY, esa clave ya está expuesta en tu sitio en vivo. Mueve esa llamada a una función del servidor y rota la clave en el proveedor. Vercel permite marcar variables como Secret, que quedan de solo escritura después de guardarlas; eso protege el valor en el panel, pero no evita que tu código lo exponga con un prefijo público.

¿Por qué no se aplicó mi cambio?

Cuatro razones explican casi toda la confusión:

  1. No hubo despliegue nuevo. Vercel aclara que los cambios en variables de entorno solo aplican a despliegues nuevos. Cambiar el valor y recargar la página no hace nada; vuelve a desplegar.
  2. Entorno equivocado. Agregaste la variable en Production pero estás probando un preview, o al revés.
  3. Grabado al compilar. Las variables públicas se congelan dentro del bundle durante el build. Aunque la app renderice en el servidor, esas salen del build y no del panel en el momento de cada petición.
  4. Errores invisibles. Un espacio al final, comillas pegadas dentro del valor, o SUPABASE_URL en el panel mientras el código lee VITE_SUPABASE_URL.

¿Cómo veo qué está usando realmente un despliegue?

  • En Vercel, la variable de sistema VERCEL_ENV vale production, preview o development, así que tu código sabe dónde está corriendo. Puedes mostrarla en el pie de página de los builds que no son de producción o registrarla en una función del servidor.
  • En el navegador, abre la pestaña Network y mira a qué URL de proyecto de Supabase van las peticiones. Eso te dice al instante si un preview está hablando con producción.
  • Desde la CLI, vercel env ls lista lo configurado en cada entorno y vercel env pull escribe tus variables de Development en un archivo .env local.
  • Con los secretos, nunca imprimas el valor. Registra si existe (Boolean(process.env.STRIPE_SECRET_KEY)) y, si hace falta, el prefijo, como sk_test frente a sk_live.

¿Cómo se ve una configuración local ordenada?

  1. Sube al repositorio un .env.example con todos los nombres de variables y ningún valor real.
  2. Guarda los valores reales en .env.local, que las plantillas de Vite y Next.js ignoran en Git por defecto. Igual revisa tu .gitignore.
  3. Apunta el entorno local a pruebas o a una instancia local de Supabase, nunca a producción.
  4. Si alguna vez subiste a GitHub un .env con claves reales, borrarlo no alcanza. Las claves quedan en el historial, así que rótalas.

Respuestas rápidas

¿Tengo que volver a desplegar después de cambiar una variable? Sí. Los despliegues existentes conservan los valores con los que se compilaron.

¿Un preview puede usar las variables de producción? Técnicamente sí, pero entonces las ramas de prueba escriben en datos reales y pueden cobrar tarjetas reales. Dale a los previews sus propios valores.

¿La clave anon de Supabase es secreta? No, está pensada para ser pública, pero solo Row Level Security la hace segura. Lo explicamos en la guía sobre si la clave anon de Supabase es segura.

¿Qué tamaño pueden tener las variables en Vercel? El total por despliegue es de 64 KB sumando todas, con un límite menor por variable en las funciones edge.

¿Quieres tus entornos bien separados?

Separar producción de todo lo demás es de las formas más baratas de evitar un mal día. Nuestros planes de mantenimiento de software incluyen configurar entornos y rotar claves filtradas, y el checklist de seguridad para apps hechas con IA cubre lo que conviene revisar después. También puedes pasar tu app por el chequeo gratuito para ver si algo sensible se ve desde afuera.

¿Tu app sigue trabada?

Pasa el chequeo gratis con la URL de tu app, o pide la Auditoría de rescate de $299: un ingeniero senior revisa el código y te envía un informe escrito en 2 días hábiles.