3 esquemas PostgreSQL para una aplicación limpia — estructurar Supabase desde el principio
Cuando inicia un proyecto, la tentación es grande de poner todo en el esquema public de PostgreSQL. Una tabla aquí, otra allá, y en tres semanas se encuentra con 40 tablas mezcladas sin ninguna lógica.
Decidí muy pronto estructurar TAMSIV con tres esquemas separados.
Los tres esquemas
privat— Todos los datos personales: tareas, notas, eventos del calendario, perfiles de usuario, archivos adjuntoscollaborative— Todo lo relacionado con los grupos: miembros, roles, tareas compartidas, listas de verificación de grupogamification— Las estadísticas, insignias, rachas, desafíos diarios, historial de puntos
¿Por qué privat y no private? Porque private es una palabra reservada en SQL. Lo aprendí por las malas después de una migración fallida.
¿Por qué separar?
1. La legibilidad. Cuando hago SELECT * FROM privat.tasks, sé inmediatamente que es un dato personal.
2. La seguridad. Las políticas RLS son más fáciles de razonar cuando las tablas están agrupadas por dominio. Las reglas del esquema privat son simples: usted solo ve sus datos. Las del esquema collaborative son más complejas: usted ve los datos de los grupos de los que es miembro, según su rol.
3. La evolución. Cuando agregué la gamificación tres meses después del inicio del proyecto, creé un nuevo esquema sin tocar los otros dos. Cero riesgo de romper lo existente.
La pesadilla de las políticas RLS
Supabase utiliza RLS para asegurar el acceso a los datos. El principio es simple: cada tabla tiene reglas que determinan quién puede leer, escribir, modificar, eliminar. En la práctica, es un laberinto.
En total, el proyecto cuenta con más de 30 políticas RLS. Cada una probada individualmente.
Las convenciones de nomenclatura
Adopté convenciones estrictas: tablas en snake_case en plural, columnas en snake_case, parámetros RPC con prefijo p_. Este prefijo p_ evita colisiones con los nombres de las columnas en las consultas. El día que su parámetro user_id entra en conflicto con la columna user_id, usted entiende por qué.
Esta estructura me ahorró un tiempo considerable en el futuro. Cada nueva característica encuentra su lugar de forma natural.