Cómo un JSON enorme en user_metadata de Supabase puede romper tu aplicación
Los productos rara vez caen por una única decisión catastrófica. Caen por una cadena de atajos «inofensivos» que crece en silencio hasta que todo salta.
`user_metadata` de Supabase es una trampa así: útil al principio, peligrosa al escalar y demasiado fácil de usar mal.
Se trata como un cajón para datos del usuario. Solo es JSON, ¿no? Sí, con una consecuencia: Supabase incluye metadata en el JWT de sesión. En el escenario con cookies que describo, ese token viaja con las peticiones. Más metadata, peticiones mayores.
No es un patrón de almacenamiento. Es un patrón de carga transportada. Tiene consecuencias de arquitectura.

El mecanismo oculto
El camino:
1. Guardas datos en `auth.users.user_metadata`.
2. Supabase refleja metadata en el JWT.
3. El JWT se guarda en cookies.
4. Las cookies viajan con las peticiones.
5. Toda la cadena transporta datos personales que no necesitaba.
Funciona hasta que deja de funcionar.
Unos pocos campos parecen inocentes. Añade comportamiento, estado de UI, preferencias de directorios y análisis del perfil. Crecen peticiones y cabeceras, depurar se vuelve incoherente y la autenticación parece un semáforo en cortocircuito.
Acaba rompiéndose algo. Síntomas:
Da igual lo limpio que sea tu código. La autenticación es el cuello de botella.
Cuando me pasó
No hablo de teoría. Me di contra esa pared.
Pasé dos fines de semana enteros investigando una autenticación de pronto inestable. Sin grandes despliegues ni funciones complejas. Solo añadidos pequeños a `user_metadata`: una línea aquí, un estado de UI allá.
Nada que pareciera peligroso. Todo lo que sí lo era.
No era la base. Ni la infraestructura. Ni el rendimiento en el sentido habitual. Era el JWT.
El token debía ser una llave y se había convertido en una maleta de JSON arrastrada en cada petición. No por megabytes, sino por unas decenas de líneas de metadata acumuladas más allá de lo razonable.
No una brecha espectacular. Una asfixia lenta.
El principio que nadie enseña
Sesión ≠ almacén
Tu JWT no es un almacén, una caché ni un contenedor del contexto cambiante del producto.
Debe ser pequeño, previsible, estable y aburrido. Lo demás tiene otro sitio.
¿Saber quién es el usuario? Bien. ¿Sus preferencias, analítica, estado de UI, acciones recientes y media hoja de ruta? Estás metiendo el producto en el pasaporte. Y los pasaportes no sirven para transportar muebles.
El patrón correcto
Usa `user_metadata` para lo que cabe en una tarjeta de visita. El resto, a tablas dedicadas.
Mi regla: contexto de identidad en `user_metadata`; lo demás, tablas propias. ¿Cambia con el tiempo? No lo metas en la sesión. ¿Parece cómodo? Cuestiónalo. ¿Dudas? Sepáralo.
La visión completa
No va solo de Supabase, sino de productos que escalan frente a productos que acumulan entropía.
Los pequeños errores aparecen cuando el producto empieza a ganar tracción: el peor momento para una sorpresa.
¿La sesión pesa demasiado? ¿Los registros de acceso son acertijos? ¿Metadata hace más trabajo que la base? Estás al principio de un fallo evitable. Lo bueno: se puede arreglar.
Conclusión
Los productos que funcionan no se ahogan en sus datos. Los estructuran.
Autenticar debería ser un apretón de manos, no un servicio de carga. Si el JWT lleva metadata en lugar de identidad, no escalas: te atascas. Y puedes corregirlo antes de que salga caro.
Hablemos de claridad.


