Por qué elegí Supabase para una app de citas que estoy montando por las tardes

Por qué elegí Supabase para una app de citas que estoy montando por las tardes
ContenidoContents

En ratos sueltos por las tardes estoy montando una app de citas. Nada que vaya a cambiarle la vida a nadie, un proyecto personal para aprender montando algo con usuarios reales de por medio, que es donde de verdad se aprende. Antes de escribir la primera línea de backend le pregunté a Claude Code qué usar, y me propuso Supabase. Lo conocía de oídas — “un Firebase de código abierto” — pero de oídas no es suficiente cuando lo que vas a colgar ahí son cuentas, ubicaciones y fotos de gente real.

Así que antes de meter nada, primero entendí qué había debajo.

Qué es Supabase, en cristiano

Supabase es un Postgres gestionado con una caja de herramientas encima. La base es una base de datos PostgreSQL de verdad, sin recortes, y alrededor te monta lo que en cualquier app necesitas construir a mano:

  • Auth: login por email, teléfono o redes sociales, con sesiones y tokens ya resueltos.
  • Storage: subida de ficheros (fotos, avatares) con buckets públicos o privados.
  • Realtime: te enteras al instante de los cambios en la base de datos — útil para chat o para saber quién está conectado ahora mismo.
  • Edge Functions: código propio que corre en su infraestructura cuando lo necesitas.
  • API autogenerada: PostgREST lee el esquema de tu base de datos y te monta una API REST sin que escribas un solo endpoint.

La diferencia con Firebase, que es con quien siempre se le compara, no es de matiz: Firebase es NoSQL y propietario; si algún día quieres irte, te llevas un volcado de JSON y a reconstruir las relaciones tú. Supabase es Postgres estándar. Si algún día me quiero ir, me llevo un pg_dump y monto esa misma base de datos donde quiera, porque es open source y se puede autoalojar. De momento uso su nube, pero sirve saber que la puerta de salida no está tapiada.

Por qué encaja con esta app en concreto

No es una elección abstracta de “Postgres es mejor que NoSQL”. Son cinco cosas muy concretas que esta app necesitaba y que Supabase ya trae resueltas.

1. Búsqueda por cercanía, sin reinventar la geometría

El corazón de una app de citas es “quién hay cerca de mí ahora mismo”. Postgres tiene una extensión, PostGIS, hecha precisamente para esto, y Supabase la activa con un clic. Guardas la ubicación como un tipo geography y preguntas por radio directamente en SQL:

1select id, nombre
2from perfiles
3where st_dwithin(
4  ubicacion,
5  st_setsrid(st_makepoint(:lng, :lat), 4326)::geography,
6  5000  -- metros
7)
8order by ubicacion <-> st_setsrid(st_makepoint(:lng, :lat), 4326)::geography
9limit 20;

Eso, calculado a mano en el backend con latitudes y longitudes, es una fuente constante de errores sutiles (la Tierra es una esfera, no un plano). Aquí es una consulta con índice espacial detrás, tan rápida como cualquier otra.

2. Row Level Security: la privacidad vive en la base de datos, no en mi código

Esto es lo que más me convenció. En una app de citas hay perfiles bloqueados, gente que no quiere ser vista por según quién, mensajes que solo deben leer dos personas. La forma habitual de resolver esto es meter comprobaciones de permisos en cada endpoint del backend. Y basta con que se te olvide una para tener una fuga de datos.

Postgres tiene Row Level Security (RLS): políticas que se evalúan en la propia base de datos, en cada fila, sin importar por dónde llegue la consulta. Una política de “solo veo mi propio perfil o los que no me han bloqueado” se escribe una vez:

1create policy "ver perfiles no bloqueados"
2on perfiles for select
3using (
4  not exists (
5    select 1 from bloqueos
6    where bloqueos.bloqueado_id = perfiles.id
7    and bloqueos.usuario_id = auth.uid()
8  )
9);

Y a partir de ahí, aunque meta la pata en el código de la app, la base de datos sigue sin devolver lo que no debe. Es la diferencia entre confiar en que el código de arriba se acuerde de comprobar el permiso, y que sea físicamente imposible saltárselo.

3. Realtime, para el chat y el “en línea ahora”

Supabase Realtime escucha los cambios de Postgres (usa la replicación lógica que ya trae el motor) y te los empuja por WebSocket. Para el chat de la app y para el típico punto verde de “activo ahora”, eso significa que no monto un servidor de WebSockets aparte ni gestiono su propio ciclo de vida: me suscribo a una tabla y punto.

4. Auth sin escribir mi propio sistema de sesiones

Login con email, con teléfono, con Google o Apple — lo típico en una app de citas, donde pedir “regístrate con un formulario y confirma el email” es fricción que pierde usuarios. Todo eso ya viene resuelto, con tokens y renovación de sesión incluidos. Escribir esto a mano no es difícil, es tedioso y fácil de dejar con un agujero.

5. Storage para las fotos, con URLs firmadas

Las fotos de perfil van en un bucket privado, no público: nadie debería poder adivinar la URL de la foto de otro. Supabase Storage genera URLs firmadas con caducidad, así que la app pide una URL temporal cada vez, en vez de servir un enlace permanente que se pueda compartir fuera de la app.

La letra pequeña

Nada de esto es gratis en el sentido de “sin coste”, solo en el sentido de “sin factura este mes”:

  • El plan gratuito pausa el proyecto tras una semana sin actividad. Para un proyecto que estoy probando por las tardes, eso significa despertarlo a mano de vez en cuando.
  • RLS hay que probarla en serio, no dar por hecho que funciona porque la política “tiene buena pinta”. Una política mal escrita puede ser tan permisiva como no tener ninguna, y el error no salta a la vista como saltaría un 500 en el backend.
  • Realtime a base de replicación lógica tiene un límite de conexiones simultáneas por proyecto en el plan gratuito, algo a vigilar si esto alguna vez tiene usuarios de verdad.

El veredicto, de momento

Para un proyecto personal que no sé si va a llegar a ningún sitio, montar mi propio Postgres, mi propio sistema de autenticación y mi propio servidor de WebSockets desde cero habría sido reinventar tres ruedas para llegar al mismo punto de partida. Supabase me ha dejado empezar por la parte interesante — el modelo de datos, las políticas de privacidad, la lógica de la app — en vez de por la fontanería.

Sigo montándola. Si llega a buen puerto, o si tropiezo con algo digno de contar por el camino, seguiré escribiendo sobre ello.

CompartirShare