Cuando lanzas un proyecto web o una app móvil, una de las primeras decisiones que tienes que tomar es dónde y cómo almacenar los datos. Montar y mantener tu propio servidor de base de datos es posible, pero implica tiempo, conocimientos de administración de sistemas y coste. Las plataformas de base de datos como servicio (DBaaS) resuelven ese problema: te dan una base de datos lista para usar en minutos, con autenticación, APIs y almacenamiento de archivos incluidos.
En 2026, las dos opciones más populares para proyectos independientes, startups y equipos pequeños son Firebase y Supabase. Se parecen en la propuesta de valor pero son fundamentalmente diferentes en su arquitectura, modelo de datos y filosofía. En esta guía vas a entender en qué consiste cada una, cuáles son sus ventajas y limitaciones reales, y cuál encaja mejor con tu proyecto.
Qué es Firebase
Firebase es la plataforma de desarrollo de aplicaciones de Google. Lanzada en 2011 y adquirida por Google en 2014, ofrece un ecosistema completo de servicios en la nube: base de datos en tiempo real, autenticación, almacenamiento de archivos, funciones serverless, hosting, analítica, notificaciones push y mucho más.
Su base de datos principal es Firestore, una base de datos NoSQL orientada a documentos. Los datos se organizan en colecciones que contienen documentos, y cada documento es un objeto JSON que puede tener subcolecciones anidadas. No hay esquema fijo: cada documento puede tener campos completamente distintos.
// Estructura de datos en Firestore
// Colección: "usuarios"
// Documento: "uid_abc123"
{
"nombre": "Ana García",
"email": "ana@mail.com",
"plan": "premium",
"creadoEn": Timestamp(2026-01-15),
"config": {
"tema": "oscuro",
"idioma": "es"
}
}
// Subcolección: "usuarios/uid_abc123/pedidos"
// Documento: "pedido_001"
{
"total": 129.99,
"estado": "enviado",
"articulos": ["prod_A", "prod_B"]
}
La característica más destacada de Firebase es la sincronización en tiempo real. Cualquier cambio en Firestore se propaga instantáneamente a todos los clientes suscritos, sin necesidad de hacer polling ni configurar WebSockets manualmente. Esto lo hace especialmente atractivo para aplicaciones colaborativas, chats, dashboards en vivo o juegos.
// Firebase: suscripción en tiempo real con el SDK web
import { db } from './firebase-config';
import { collection, onSnapshot, query, orderBy } from 'firebase/firestore';
const q = query(
collection(db, 'mensajes'),
orderBy('creadoEn', 'desc')
);
// onSnapshot se ejecuta cada vez que hay un cambio en la colección
const cancelarSuscripcion = onSnapshot(q, (snapshot) => {
const mensajes = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
actualizarUI(mensajes);
});
// Cancelar la suscripción al desmontar el componente
return () => cancelarSuscripcion();
Qué es Supabase
Supabase es una plataforma open source lanzada en 2020 que se presenta abiertamente como "la alternativa open source a Firebase". Su propuesta es diferente desde la base: en lugar de una base de datos NoSQL, usa PostgreSQL, la base de datos relacional más avanzada del mundo open source.
Esto significa que en Supabase tienes tablas, filas, columnas con tipos de datos fijos, claves foráneas, joins, índices, vistas, funciones y procedimientos almacenados. Si sabes SQL, te sentirás en casa desde el primer momento. Si no lo sabes, Supabase es también un excelente punto de partida para aprenderlo.
-- En Supabase trabajas con SQL estándar de PostgreSQL
CREATE TABLE usuarios (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
nombre TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
plan TEXT DEFAULT 'gratuito' CHECK (plan IN ('gratuito', 'pro', 'premium')),
creado_en TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE pedidos (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
total NUMERIC(10, 2) NOT NULL CHECK (total > 0),
estado TEXT DEFAULT 'pendiente',
creado_en TIMESTAMPTZ DEFAULT NOW()
);
-- Consulta con JOIN: algo imposible en Firestore sin hacer múltiples peticiones
SELECT
u.nombre,
u.email,
COUNT(p.id) AS total_pedidos,
SUM(p.total) AS gasto_total
FROM usuarios u
LEFT JOIN pedidos p ON p.usuario_id = u.id
GROUP BY u.id, u.nombre, u.email
ORDER BY gasto_total DESC;Supabase también ofrece tiempo real, pero implementado sobre las capacidades de replicación de PostgreSQL (Realtime). Autenticación, almacenamiento de archivos, funciones Edge (serverless) y una API REST y GraphQL generadas automáticamente completan el stack.
// Supabase: tiempo real con el SDK JavaScript
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// Suscribirse a cambios en una tabla
const canal = supabase
.channel('cambios-mensajes')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'mensajes' },
(payload) => {
console.log('Cambio recibido:', payload);
actualizarUI(payload.new);
}
)
.subscribe();
// Cancelar suscripción
supabase.removeChannel(canal);
Autenticación: cómo gestiona usuarios cada plataforma
Ambas plataformas incluyen un sistema de autenticación completo que elimina la necesidad de implementar login desde cero.
Firebase Authentication
Firebase Authentication es uno de los sistemas más maduros del mercado. Soporta email/contraseña, número de teléfono (OTP por SMS), proveedores sociales (Google, Facebook, Twitter, GitHub, Apple, Microsoft) y SAML/OIDC para empresas. Su integración con el resto del ecosistema Firebase es perfecta.
// Firebase: registro y login con email
import { auth } from './firebase-config';
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signInWithPopup,
GoogleAuthProvider,
onAuthStateChanged,
signOut
} from 'firebase/auth';
// Registro
async function registrar(email, contrasena) {
const credencial = await createUserWithEmailAndPassword(auth, email, contrasena);
return credencial.user;
}
// Login con Google en un popup
async function loginConGoogle() {
const proveedor = new GoogleAuthProvider();
const resultado = await signInWithPopup(auth, proveedor);
return resultado.user;
}
// Observar cambios en la sesión
onAuthStateChanged(auth, (usuario) => {
if (usuario) {
console.log('Sesión activa:', usuario.email);
} else {
console.log('Sin sesión');
}
});
// Cerrar sesión
await signOut(auth);
Supabase Auth
Supabase Auth soporta email/contraseña con confirmación por correo, Magic Link (login sin contraseña), proveedores sociales (Google, GitHub, Discord, Twitter, Apple, Spotify y más), y OTP por SMS. Una ventaja importante: la gestión de sesiones se integra nativamente con las políticas de seguridad de PostgreSQL (Row Level Security), lo que permite controlar el acceso a los datos directamente en la base de datos.
// Supabase: registro, login y sesión
import { supabase } from './supabase-config';
// Registro con confirmación por email
async function registrar(email, contrasena) {
const { data, error } = await supabase.auth.signUp({ email, password: contrasena });
if (error) throw error;
return data.user;
}
// Login con Magic Link (sin contraseña)
async function loginMagicLink(email) {
const { error } = await supabase.auth.signInWithOtp({ email });
if (error) throw error;
// El usuario recibe un enlace en su correo para iniciar sesión
}
// Login con proveedor OAuth
async function loginConGithub() {
const { error } = await supabase.auth.signInWithOAuth({ provider: 'github' });
if (error) throw error;
}
// Obtener la sesión actual
const { data: { session } } = await supabase.auth.getSession();
console.log(session?.user?.email);
// Escuchar cambios de sesión
supabase.auth.onAuthStateChange((evento, sesion) => {
console.log(evento, sesion?.user?.email);
});
Seguridad: cómo controlan el acceso a los datos
Este es uno de los puntos más importantes y donde las dos plataformas tienen enfoques distintos.
Firebase: Security Rules
Firebase usa un lenguaje propio de reglas de seguridad que se define en un archivo de configuración. Las reglas controlan quién puede leer y escribir cada colección o documento.
// firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Los usuarios solo pueden leer y editar su propio documento
match /usuarios/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
// Los pedidos: el dueño puede leer los suyos, solo el servidor puede escribir
match /pedidos/{pedidoId} {
allow read: if request.auth != null
&& request.auth.uid == resource.data.usuarioId;
allow write: if false; // solo desde Cloud Functions (servidor)
}
// Posts públicos: cualquiera puede leer, solo autenticados pueden crear
match /posts/{postId} {
allow read: if true;
allow create: if request.auth != null
&& request.resource.data.autorId == request.auth.uid;
allow update, delete: if request.auth != null
&& resource.data.autorId == request.auth.uid;
}
}
}
Supabase: Row Level Security (RLS)
Supabase usa Row Level Security, una característica nativa de PostgreSQL. Las políticas de seguridad se escriben en SQL y se aplican a nivel de fila: cada consulta pasa por el filtro de las políticas antes de acceder a los datos. Es más potente y expresivo que las Security Rules de Firebase porque puedes usar toda la expresividad de SQL.
-- Activar RLS en una tabla (obligatorio para que las políticas tengan efecto)
ALTER TABLE pedidos ENABLE ROW LEVEL SECURITY;
-- Política: los usuarios solo ven sus propios pedidos
CREATE POLICY "usuarios_ven_sus_pedidos"
ON pedidos FOR SELECT
USING (auth.uid() = usuario_id);
-- Política: los usuarios solo pueden crear pedidos a su nombre
CREATE POLICY "usuarios_crean_sus_pedidos"
ON pedidos FOR INSERT
WITH CHECK (auth.uid() = usuario_id);
-- Política: solo el admin puede ver todos los pedidos
CREATE POLICY "admin_ve_todo"
ON pedidos FOR ALL
USING (
EXISTS (
SELECT 1 FROM usuarios
WHERE id = auth.uid() AND rol = 'admin'
)
);
-- Política en posts: cualquiera puede leer, solo el autor puede modificar
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "posts_publicos" ON posts FOR SELECT USING (true);
CREATE POLICY "autor_modifica_su_post" ON posts
FOR UPDATE USING (auth.uid() = autor_id);
Consultas y acceso a datos
Aquí es donde la diferencia entre NoSQL y SQL se hace más evidente y más importante para elegir bien.
Firestore: consultas limitadas pero reactivas
Firestore tiene un modelo de consultas con limitaciones importantes: no puedes hacer joins entre colecciones, no puedes usar OR en múltiples campos, y las consultas compuestas requieren crear índices manualmente en la consola de Firebase. Para consultas complejas, tienes que hacer múltiples peticiones y combinar los resultados en el cliente.
import { db } from './firebase-config';
import {
collection, query, where, orderBy, limit,
getDocs, addDoc, updateDoc, deleteDoc,
doc, serverTimestamp
} from 'firebase/firestore';
// Leer con filtros
const q = query(
collection(db, 'productos'),
where('disponible', '==', true),
where('precio', '<=', 100),
orderBy('precio', 'asc'),
limit(20)
);
const snapshot = await getDocs(q);
const productos = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
// Crear
await addDoc(collection(db, 'productos'), {
nombre: 'Teclado mecánico',
precio: 89.99,
disponible: true,
creadoEn: serverTimestamp()
});
// Actualizar (solo los campos indicados)
const ref = doc(db, 'productos', 'producto_id_aqui');
await updateDoc(ref, { precio: 79.99, disponible: false });
// Eliminar
await deleteDoc(doc(db, 'productos', 'producto_id_aqui'));
Supabase: el poder completo de PostgreSQL
Con Supabase tienes acceso a toda la potencia de SQL: joins, agregaciones, subconsultas, búsqueda de texto completo, datos geoespaciales con PostGIS, búsqueda vectorial para IA y cualquier cosa que PostgreSQL soporte.
import { supabase } from './supabase-config';
// Leer con filtros
const { data: productos, error } = await supabase
.from('productos')
.select('id, nombre, precio, categoria(nombre)') // join automático con tabla categorias
.eq('disponible', true)
.lte('precio', 100)
.order('precio', { ascending: true })
.limit(20);
// Crear
const { data, error } = await supabase
.from('productos')
.insert({ nombre: 'Teclado mecánico', precio: 89.99, disponible: true })
.select()
.single();
// Actualizar
const { data, error } = await supabase
.from('productos')
.update({ precio: 79.99, disponible: false })
.eq('id', 'producto_id_aqui')
.select()
.single();
// Eliminar
const { error } = await supabase
.from('productos')
.delete()
.eq('id', 'producto_id_aqui');
// SQL nativo para consultas complejas
const { data } = await supabase.rpc('obtener_estadisticas_ventas', {
fecha_inicio: '2026-01-01',
fecha_fin: '2026-12-31'
});
// Búsqueda de texto completo
const { data } = await supabase
.from('productos')
.select()
.textSearch('nombre', 'teclado mecánico', { type: 'websearch' });
Almacenamiento de archivos
Ambas plataformas incluyen almacenamiento de archivos como parte de su oferta, con control de acceso integrado con el sistema de autenticación.
// Firebase Storage: subir y obtener URL pública
import { storage } from './firebase-config';
import { ref, uploadBytes, getDownloadURL, deleteObject } from 'firebase/storage';
async function subirImagen(archivo, usuarioId) {
const referencia = ref(storage, `avatares/${usuarioId}/${archivo.name}`);
const resultado = await uploadBytes(referencia, archivo);
const url = await getDownloadURL(resultado.ref);
return url;
}
// Supabase Storage: subir y obtener URL pública
async function subirImagen(archivo, usuarioId) {
const ruta = `avatares/${usuarioId}/${archivo.name}`;
const { error } = await supabase.storage
.from('imagenes') // nombre del bucket
.upload(ruta, archivo, { upsert: true });
if (error) throw error;
const { data } = supabase.storage
.from('imagenes')
.getPublicUrl(ruta);
return data.publicUrl;
}
Precios: dónde más difieren en la práctica
El modelo de precios es uno de los factores más importantes para proyectos reales y es donde las diferencias son más significativas.
Firebase (plan Spark, gratuito) incluye 1 GB de almacenamiento en Firestore, 50.000 lecturas y 20.000 escrituras diarias, 10 GB de transferencia de datos al mes, 1 GB en Storage y autenticación ilimitada. El plan de pago (Blaze) es de pago por uso: cobran por lectura, escritura y eliminación de documentos. Con tráfico alto, la factura puede escalar muy rápido y de forma difícil de predecir, especialmente si tus queries leen muchos documentos.
Supabase (plan gratuito) incluye 2 proyectos activos, 500 MB de base de datos PostgreSQL, 1 GB de almacenamiento de archivos, 50.000 usuarios activos mensuales y 2 GB de transferencia. El plan Pro cuesta 25 dólares al mes por proyecto con límites mucho más generosos. El modelo de precios es más predecible porque no cobran por número de operaciones sino por recursos consumidos (tamaño de la base de datos, transferencia).
Para proyectos en crecimiento, Supabase suele resultar más económico y predecible. Firebase puede ser más barato en proyectos muy pequeños con pocas operaciones, pero escala en coste de forma más agresiva.
Funciones serverless
Ambas plataformas permiten ejecutar código del lado del servidor sin gestionar infraestructura.
// Firebase Cloud Functions: se despliegan en la infraestructura de Google
const { onRequest } = require('firebase-functions/v2/https');
const { onDocumentCreated } = require('firebase-functions/v2/firestore');
// Función HTTP
exports.procesarPago = onRequest(async (req, res) => {
const { cantidad, moneda } = req.body;
// lógica del pago...
res.json({ ok: true, transaccionId: 'txn_123' });
});
// Trigger: se ejecuta cuando se crea un documento en Firestore
exports.alCrearPedido = onDocumentCreated('pedidos/{pedidoId}', async (evento) => {
const pedido = evento.data.data();
await enviarEmailConfirmacion(pedido.emailCliente, pedido);
});
// Supabase Edge Functions: basadas en Deno, se ejecutan en el edge
// supabase/functions/procesar-pago/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
serve(async (req) => {
const { cantidad, moneda } = await req.json();
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
// lógica del pago y registro en la base de datos...
return new Response(
JSON.stringify({ ok: true }),
{ headers: { 'Content-Type': 'application/json' } }
);
});
Cuándo elegir Firebase
- Tu aplicación necesita sincronización en tiempo real como característica principal: chats, herramientas colaborativas, notificaciones instantáneas, juegos.
- Desarrollas una app móvil (iOS o Android) y quieres un SDK nativo maduro y bien integrado con el ecosistema de Google (Analytics, Crashlytics, Remote Config, Push Notifications).
- Tu equipo no tiene experiencia con bases de datos relacionales y el modelo de documentos resulta más intuitivo para el tipo de datos que manejas.
- Necesitas un backend sin código prácticamente: Firebase te permite ir muy lejos con solo el SDK del cliente y las Security Rules.
- Tu proyecto está en el ecosistema de Google Cloud y quieres aprovechar la integración nativa con otros servicios como BigQuery, Cloud Run o Google Analytics.
- El volumen de datos y operaciones es pequeño y el plan gratuito cubre tus necesidades sin preocuparte por facturas sorpresa.
Cuándo elegir Supabase
- Tus datos tienen relaciones complejas entre entidades y necesitas joins, integridad referencial o consultas analíticas. Un e-commerce, un SaaS con múltiples entidades relacionadas o cualquier aplicación con datos estructurados encaja mucho mejor en PostgreSQL.
- Ya sabes SQL o quieres aprenderlo. Supabase es una forma excelente de aprender bases de datos relacionales con un entorno moderno.
- Necesitas migraciones de base de datos versionadas y reproducibles, algo que Firebase no soporta.
- El open source es importante para ti: puedes autoalojar Supabase en tu propio servidor y no depender de ningún proveedor.
- Quieres un modelo de precios más predecible. Con Supabase sabes exactamente cuánto vas a pagar cada mes.
- Necesitas capacidades avanzadas de PostgreSQL: búsqueda vectorial para IA (pgvector), datos geoespaciales (PostGIS), búsqueda de texto completo o extensiones personalizadas.
- Vienes del mundo backend y prefieres trabajar con herramientas estándar (SQL, REST, migraciones) en lugar de aprender una API propietaria.
Comparativa directa
| Característica | Firebase | Supabase |
|---|---|---|
| Tipo de base de datos | NoSQL (Firestore, documentos) | SQL (PostgreSQL) |
| Tiempo real | Excelente, nativo y muy maduro | Bueno, sobre replicación de PostgreSQL |
| Consultas complejas | Limitadas, sin joins | Completas, SQL nativo |
| Migraciones de esquema | No (sin esquema fijo) | Sí, con control de versiones |
| Autenticación | Muy madura, muchos proveedores | Completa, Magic Link incluido |
| Seguridad de datos | Security Rules (lenguaje propio) | Row Level Security (SQL nativo) |
| Funciones serverless | Cloud Functions (Node.js) | Edge Functions (Deno / TypeScript) |
| Almacenamiento de archivos | Firebase Storage | Supabase Storage |
| Plan gratuito | Generoso para lecturas | 2 proyectos, 500 MB BD |
| Coste en producción | Por operación (puede escalar fuerte) | Por recursos (más predecible) |
| Open source | No | Sí, autoalojable |
| Ecosistema móvil | Excelente (iOS, Android, Flutter) | Bueno (iOS, Android, Flutter) |
| Curva de aprendizaje | Baja para empezar | Media (requiere SQL básico) |
| Proveedor | Supabase Inc. (open source) |
¿Puedes migrar de una a otra?
Migrar de Firebase a Supabase (o al revés) no es trivial porque el modelo de datos es fundamentalmente diferente. Exportar documentos de Firestore y convertirlos en tablas relacionales requiere rediseñar el esquema de datos, no solo mover archivos. Cuanto antes tomes la decisión correcta, menos trabajo de migración tendrás en el futuro.
Si empiezas un proyecto nuevo, dedica tiempo a analizar qué tipo de datos vas a manejar y si las relaciones entre ellos son complejas. Esa respuesta, más que cualquier otra consideración, debería guiar tu decisión.
Resumen
Elige Firebase si tu aplicación vive del tiempo real, si desarrollas apps móviles en el ecosistema Google, si el modelo de documentos encaja de forma natural con tus datos, o si quieres un backend funcional lo antes posible con la menor fricción.
Elige Supabase si tus datos tienen relaciones entre entidades, si necesitas consultas SQL complejas, si valoras el open source y la portabilidad, o si quieres aprender o aprovechar el poder de PostgreSQL con una experiencia de desarrollo moderna.
En 2026 ambas son opciones sólidas y con futuro garantizado. Firebase tiene detrás el respaldo y la infraestructura de Google. Supabase ha crecido a un ritmo impresionante, tiene una comunidad muy activa y su apuesta por el open source y PostgreSQL le da una ventaja estructural para proyectos que necesitan control total sobre sus datos.
No hay comentarios todavía. Sé el primero en compartir tu opinión.