typescript · nestjs · supabase · drizzleorm

Un repaso sencillo de lo esencial de Supabase

6 min de lectura

Imaginemos la situación: estamos construyendo nuestro próximo proyecto y sabemos que necesitamos autenticación, una base de datos y tal vez almacenamiento. Podríamos pasar días configurando Postgres, montando la autenticación desde cero y gestionando el deploy… o podríamos tenerlo todo funcionando en menos de 5 minutos.

En la era del vibe coding, herramientas como Supabase y Firebase se imponen porque resuelven exactamente este problema. Permiten lanzar rápido sin pelearse con la infraestructura.

Pero aquí es donde se pone interesante: al combinar Supabase con un backend propio en NestJS, no se sacrifica control a cambio de velocidad — se obtienen ambas cosas. Control total sobre la lógica de la base de datos, reglas de negocio personalizadas, un flujo de auth propio y la capacidad de escalar exactamente como se quiera. Sin vendor lock-in, sin el típico “esta función no está soportada”.

En este artículo veremos cómo configurar Supabase como base de una API en NestJS que ofrece lo mejor de ambos mundos.

Entendiendo Postgres + Auth

Esto es lo que hace especial a Supabase: no se trata solo de tener una base de datos y un sistema de auth como herramientas separadas. Se obtiene una base de datos que sabe quiénes son los usuarios.

Base de datos Postgres

Supabase ofrece una base de datos PostgreSQL de nivel de producción, con tres formas de acceder a ella:

  • Conexión directa: conectarse con cualquier cliente de Postgres usando el connection string (esto es lo que usaremos con Drizzle)

  • REST API: PostgREST genera automáticamente una API RESTful para las tablas, sin necesidad de backend

  • Suscripciones en tiempo real (Realtime): permiten escuchar cambios en la base de datos en tiempo real (por ejemplo, documentos colaborativos o dashboards en vivo)

¿Por qué importa esto? Flexibilidad. Se puede empezar con la conexión directa para la API de NestJS, pero si hace falta prototipar una función rápida, se puede llamar directamente a la REST API desde el frontend. ¿Se necesitan actualizaciones en vivo? Se activan las suscripciones en tiempo real. La misma base de datos, múltiples patrones de acceso.

Sistema de autenticación

Supabase Auth se encarga de todo lo esperable:

  • Email/contraseña y magic links

  • Proveedores OAuth (Google, GitHub, etc.)

  • Generación y validación de tokens JWT

  • Gestión de usuarios y sesiones

Imaginemos que existe una tabla transactions. Normalmente, habría que escribir lógica en el backend para asegurarse de que cada usuario solo vea sus propias transacciones. Con RLS, esa regla se escribe una sola vez a nivel de base de datos:

Pero aquí es donde se pone potente: Row Level Security (RLS).

CREATE POLICY "Users can only see their own transactions"
ON transactions FOR SELECT
USING (auth.uid() = user_id);

Ahora la base de datos aplica esto automáticamente. Ya sea que se acceda a través de la API de NestJS, de la REST API o directamente, cada usuario solo puede ver sus propios datos. Sin queries que dejen escapar datos, sin comprobaciones de permisos olvidadas en el código.

Y como Supabase almacena los datos de auth en el schema auth de la misma base de datos, se pueden hacer joins con las tablas de auth en las queries, extender los perfiles de usuario o añadir custom claims — todo dentro de Postgres.

Creación del proyecto de Supabase

Bien, manos a la obra. Vamos a supabase.com y creamos un nuevo proyecto. El proceso toma unos 5 minutos en total, y esto es lo que hay que hacer:

1. Iniciar sesión y crear un nuevo proyecto

  • Iniciar sesión en la cuenta de Supabase (o crear una si aún no se tiene)

  • Hacer clic en “New Project”

  • Elegir la organización o crear una nueva

2. Configurar el proyecto

  • Nombrar el proyecto (por ejemplo, “Finance-API”)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1770603544395/73f83df2-7ab2-45e5-8048-3bd5acbdc51b.jpeg align=“center”)

  • Configurar una contraseña de base de datos: hacer clic en el botón “Generate a password”. Esta es la contraseña de la base de datos Postgres, así que hay que guardarla en un lugar seguro (gestor de contraseñas, archivo .env, o donde se guarden los secretos). Se necesitará más adelante.

  • Elegir la región: seleccionar la más cercana a los usuarios. Esto afecta la latencia: un proyecto en us-east-1 será notablemente más lento para usuarios en Europa o Asia. Si no se está seguro, por ahora conviene elegir la región más cercana a uno mismo.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1770603568892/3d20439a-4b0b-4178-a115-bb30c0fbe296.jpeg align=“center”)

3. Esperar el aprovisionamiento

Hacer clic en “Create new project” y esperar entre 2 y 3 minutos. Supabase está levantando la instancia de Postgres, configurando auth y ajustando todo detrás de escena.

Una vez listo, aparecerá el dashboard del proyecto con todos los detalles de conexión, las API keys y la información de la base de datos. Sin embargo, antes de conectar nada, hace falta entender cómo funcionan las API keys de Supabase, porque usar la incorrecta puede generar problemas de seguridad.

Una breve nota sobre las API keys

Antes de seguir, es posible notar que Supabase ofrece dos API keys en el dashboard: una publishable key y una secret key. La cuestión es esta: no se va a usar ninguna de las dos en este proyecto.

La conexión a Supabase se hará mediante el connection string directo de Postgres, con Drizzle. Esto da control total sobre las queries de la base de datos y permite usar el ORM type-safe de Drizzle en lugar de las client libraries de Supabase.

Entonces, ¿para qué mencionar las API keys? Porque igualmente conviene entender para qué sirven:

Publishable Key (anon key)

  • Segura para exponer en código client-side (React, Vue, apps móviles)

  • Respeta las políticas de Row Level Security

  • Ideal si el frontend necesita hablar directamente con Supabase

Secret Key (service_role key)

  • Se salta TODAS las políticas de seguridad: actúa como admin

  • Solo para backend, nunca debe exponerse

  • Útil para migrations, scripts de administración o background jobs

💡
Para esta serie: se está usando el connection string para el backend de NestJS. Pero si más adelante se quiere agregar un frontend en React que lea datos directamente desde Supabase, ahí se usaría la publishable key. Herramientas distintas para trabajos distintos.

Bien, con esto aclarado, repasemos lo que realmente se cubrió en este artículo.

Cierre

Llegados a este punto, ya se tiene un proyecto de Supabase listo para producción, con Postgres y Auth configurados. Esto es lo que ya queda claro:

  • Por qué Supabase + NestJS es potente: se obtiene la velocidad de un BaaS con el control de un backend propio

  • Cómo se integran Postgres y Auth: Row Level Security permite que la base de datos aplique los permisos automáticamente, eliminando categorías enteras de bugs de seguridad

  • Las opciones de conexión: conexión directa (la que se usará), REST API o Realtime, cada una pensada para casos de uso distintos

  • La base ya está lista: el proyecto de Supabase está activo y esperando una conexión

¿El siguiente paso? Conectar la app de NestJS a esta instancia de Supabase usando Drizzle. Eso implica configurar un módulo de configuración que maneje las credenciales de la base de datos de forma segura.

💡
Eso se verá en el próximo artículo. Vamos a conectar el connection string, configurar Drizzle y dejar todo listo para empezar a construir la Finance API.

¡Nos vemos ahí! 🚀