---
title: "Supabase Auth para CRM multi-tenant: implementación"
description: "Cómo usar Supabase Auth para CRM a medida multi-tenant en LATAM: RBAC, RLS por tenant, JWT custom claims y aislamiento garantizado a nivel base de datos."
slug: "supabase-auth-para-crm-a-medida-con-multi-tenant"
url: "https://catalizadora.ai/blog/supabase-auth-para-crm-a-medida-con-multi-tenant"
cluster: "software-medida/supabase-auth-crm"
author: "Pablo Estrada"
published_at: "2026-05-11T12:00:00+00:00"
updated_at: "2026-06-19T19:59:51.42746+00:00"
read_minutes: "6"
lang: "es"
---
# Supabase Auth para CRM multi-tenant: implementación

> Cómo usar Supabase Auth para CRM a medida multi-tenant en LATAM: RBAC, RLS por tenant, JWT custom claims y aislamiento garantizado a nivel base de datos.

Supabase Auth con Row Level Security es la opción correcta para CRM a medida multi-tenant en LATAM. Cada usuario ve solo lo que su tenant permite, la separación está en la capa base de datos (no en código aplicación), y cero riesgo de leak entre tenants. Catalizadora construyó plataforma para 100 franquicias internacionales con este patrón. Sin retainers, sin licencias atadas, código a tu nombre.

## ¿Qué es multi-tenant en CRM y por qué es difícil?

Multi-tenant significa: un solo deploy del sistema sirve a N organizaciones (tenants) que no pueden ver datos entre sí. Cada tenant tiene sus usuarios, sus clientes, sus deals, sus reportes. Cero leak entre tenants es requisito no negociable.

El error clásico es manejar tenancy en código aplicación: cada query agrega "WHERE tenant_id = X" según el usuario. Funciona hasta que hay un bug, un endpoint que olvida agregar el filtro, o un developer que ejecuta query sin pensar. Resultado: tenant A ve datos de tenant B. Disaster comercial y legal.

La solución correcta es manejar tenancy en la capa base de datos con Row Level Security (RLS). Las políticas filtran automáticamente cada query según el JWT del usuario. Aunque el código aplicación tenga bug, la base no devuelve filas no autorizadas.

## ¿Cómo funciona RLS con Supabase?

Supabase es PostgreSQL gestionado. RLS es feature nativa de PostgreSQL desde 2017. El flujo:

- Usuario se autentica vía Supabase Auth (email password, magic link, OAuth, OTP)
- Supabase emite JWT con campos estándar (id, email, role) más custom claims (tenant_id, oficina_id, rol_custom)
- App envía requests con el JWT en el header Authorization
- Supabase API ejecuta las queries pasando el JWT a PostgreSQL
- PostgreSQL aplica RLS policies que leen el JWT y filtran filas

El developer escribe el código como si fuera single-tenant. La RLS hace el filtrado por debajo. Cero código tenant-specific en la aplicación.

## El caso real: 100 franquicias internacionales con 7 roles RBAC

Catalizadora construyó la plataforma multi-tenant para una distribuidora con 100 franquicias internacionales:

- 7 roles RBAC definidos (tni_admin, tni_regional, franchise_owner, franchise_admin, franchise_manager, franchise_user, auditor)
- RLS por oficina usando JWT custom claims (auth.user_oficina_id())
- DENY UPDATE/DELETE en audit log (append-only)
- Schemas silver y gold protegidos por RLS
- Session mode connection pooler (no transaction mode)
- 3.6 millones de filas migradas a Supabase con RLS activo desde día uno

Resultado: cada franquicia ve solo sus datos. La arquitectura escala a 100 a 200 inmobiliarias bajo el mismo deploy si fuera SaaS inmobiliario.

## Estructura típica de tabla multi-tenant

Una tabla de CRM con tenant_id como columna y RLS policy:

```sql
create table public.deals (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id),
  owner_id uuid not null references auth.users(id),
  title text not null,
  amount numeric,
  stage text not null,
  created_at timestamptz default now()
);

create index deals_tenant_idx on public.deals(tenant_id);

alter table public.deals enable row level security;

create policy "deals_read_own_tenant" on public.deals
  for select
  using (tenant_id = (auth.jwt() ->> 'tenant_id')::uuid);

create policy "deals_write_own_tenant" on public.deals
  for insert with check (tenant_id = (auth.jwt() ->> 'tenant_id')::uuid);
```

Cada query del usuario lee solo deals de su tenant. Sin código aplicación tenant-specific. RLS hace el trabajo.

## JWT custom claims: cómo agregarlos

Supabase Auth permite agregar claims custom al JWT vía:

- Auth Hook (Auth Hook Send Email, Auth Hook Custom Access Token): función serverless que enriquece el JWT en cada login
- raw_app_meta_data en auth.users: campo JSON que se incluye automáticamente en cada JWT emitido
- Trigger before login que populates raw_app_meta_data

Patrón típico: cuando se crea un usuario, un trigger asigna tenant_id y rol en raw_app_meta_data. Cada login refresca el JWT con esos claims. Las policies leen el campo tenant_id desde el JWT con el operador JSON de PostgreSQL.

## Roles RBAC jerárquicos

Para un CRM multi-tenant serio, los roles típicos en LATAM:

| Rol | Permisos |
|---|---|
| super_admin (Catalizadora) | Todo en todos los tenants. Solo para soporte y migración |
| tenant_admin | Todo dentro de su tenant. CRUD usuarios, configuración, billing |
| manager | CRUD deals, reportes de su equipo. No usuarios ni billing |
| sales_rep | CRUD deals propios. Lectura de equipo |
| viewer | Solo lectura de su tenant |
| auditor | Solo lectura más audit log completo. Para compliance |

Las policies RLS implementan esta jerarquía: super_admin bypassea RLS, tenant_admin lee todo su tenant, manager filtra por equipo, sales_rep filtra por owner_id propio.

## Audit log inmutable con SHA-256

Para CRM multi-tenant con compliance (financiero, legal, salud), el audit log debe ser append-only verificable. Catalizadora implementa:

- Schema audit aparte con RLS DENY UPDATE/DELETE forzado
- Trigger en cada INSERT que calcula SHA-256 hash del registro anterior más el nuevo (hash chain)
- Función audit.verify_chain_integrity() que recalcula la cadena y detecta manipulaciones
- Cada evento tiene user_id, ip, action, table, row_id en JSON metadata

Si alguien intenta modificar audit log directamente en base, falla por RLS. Si modifica via super_admin, la hash chain se rompe en la próxima verificación.

## ¿Qué pasa con storage de archivos multi-tenant?

Supabase Storage tiene RLS análoga para buckets y objects. Patrón típico:

- Bucket por tipo (avatars, documents, attachments)
- Estructura de carpetas: `/[tenant_id]/[user_id]/[filename]`
- Policy: solo permitir acceso a objects donde el primer segmento del path coincide con tenant_id del JWT

Cada tenant ve solo sus archivos. Cero leak. Sin lógica tenant-specific en código aplicación.

## Conexión pooler: session mode vs transaction mode

Para CRM serio con RLS activo, usar session mode pooler (puerto 5432 directo o pooler en port 6543 con session mode), no transaction mode (port 6543 transaction). Razón:

- Transaction mode reinicia la sesión entre queries. El JWT context se pierde.
- Session mode mantiene la sesión durante la duración de la conexión. RLS funciona correctamente.

Catalizadora usa session mode para todas las plataformas multi-tenant sobre Supabase.

## Escalabilidad: ¿hasta cuántos tenants y usuarios?

Supabase Pro plan base maneja sin problemas:

- 50,000 a 100,000 usuarios activos por instance
- 100 a 1,000 tenants por instance
- 5 a 50 millones de filas con RLS activo (con índices correctos)

Para escalas mayores, Supabase ofrece compute upgrade lineal y eventualmente self-hosted con replicación. La distribuidora con 100 franquicias internacionales que Catalizadora construyó corre cómoda sobre Supabase Pro compute Micro.

## Stack recomendado para CRM multi-tenant 2026

| Capa | Tecnología | Razón |
|---|---|---|
| Frontend | Next.js 15 + Tailwind + shadcn/ui | RSC, app router maduro |
| Backend API | Direct Supabase + Edge Functions | Reduce hop, RLS automático |
| Auth | Supabase Auth con custom claims | Multi-tenant nativo |
| Database | Supabase Pro PostgreSQL | RLS, JSONB, pgvector |
| Storage | Supabase Storage con RLS | Archivos por tenant |
| Realtime | Supabase Realtime | Subscriptions con RLS |
| Observabilidad | Sentry + Better Stack | Errors, logs por tenant |

## Próximos pasos

Si vas a construir CRM multi-tenant serio en LATAM, Supabase Auth con RLS es la opción correcta para 90 por ciento de casos. La excepción son escalas extremas (más de 200,000 usuarios concurrentes) o requisitos regulatorios on-prem específicos.

[MAGIA Forge](https://catalizadora.ai/magia/forge) construye el CRM multi-tenant completo en 12 semanas con CI/CD, hardening, observabilidad y auditoría compliance por 20,000 USD pago único. Para CRM single-tenant más simple, [MAGIA Core](https://catalizadora.ai/magia/core) cubre por 15,000 USD. Código a tu nombre, sin retainers, sin licencias atadas.
## Preguntas frecuentes

### ¿Supabase Auth sirve para CRM multi-tenant serio?

Sí. Con Row Level Security (RLS), JWT custom claims y políticas por tenant, Supabase Auth maneja multi-tenant a escala. Catalizadora construyó plataforma para 100 franquicias internacionales sobre este patrón.

### ¿Qué es JWT custom claims y por qué importa?

Es información custom incrustada en el token JWT (tenant_id, oficina_id, rol). Las políticas RLS leen ese JWT y filtran datos automáticamente a nivel base. Cada usuario ve solo lo que su tenant le permite ver.

### ¿Cómo se evita leak de datos entre tenants?

RLS forzado en cada tabla de aplicación. La separación está en la capa base de datos, no en código aplicación. Aunque haya bug en el código, la base no devuelve filas de otro tenant. Cero riesgo de leak.

### ¿Cuántos roles RBAC se manejan típicamente?

Entre 4 y 10 roles por proyecto serio. Catalizadora implementó 7 roles RBAC para una distribuidora multi-país (tni_admin, tni_regional, franchise_owner, franchise_admin, franchise_manager, franchise_user, auditor) con permisos jerárquicos.

### ¿Qué pasa si un tenant tiene millones de filas?

RLS escala bien si las políticas están indexadas correctamente. Los índices sobre tenant_id, oficina_id o equivalente son críticos. Catalizadora migró 3.6 millones de filas a Supabase y RLS performó sin degradación.


---

Source: https://catalizadora.ai/blog/supabase-auth-para-crm-a-medida-con-multi-tenant
Author: Pablo Estrada — AI Catalyst, LLC (catalizadora.ai)
