Estás construyendo una aplicación. Los usuarios necesitan iniciar sesión. Los datos deben sincronizarse en tiempo real. Los archivos necesitan almacenamiento. Podrías levantar servidores, configurar bases de datos y gestionar la infraestructura durante semanas. O podrías usar Firebase.
Firebase potencia más de 1.5 millones de aplicaciones, incluyendo The New York Times, Duolingo y Alibaba. Los desarrolladores lo eligen porque elimina la complejidad del backend. Te enfocas en las características, no en el mantenimiento del servidor. Pero la API de Firebase tiene sus peculiaridades. Los flujos de autenticación confunden a los principiantes. Las reglas de la base de datos complican a los desarrolladores experimentados. Las Cloud Functions parecen mágicas hasta que entiendes los activadores.
He integrado Firebase en aplicaciones de producción que atienden a millones de usuarios. He cometido todos los errores posibles: expuse claves de cuentas de servicio, escribí consultas ineficientes, implementé funciones defectuosas. Esta guía destila esas lecciones.
Aprenderás autenticación, operaciones de base de datos, Cloud Functions y almacenamiento. Verás código funcional, no solo teoría. Evitarás los problemas que causan incendios en producción.
💡Probar las API de Firebase se vuelve más fácil con herramientas adecuadas de cliente API. Apidog te permite organizar puntos finales, probar flujos de autenticación y compartir colecciones con tu equipo. Mostraremos dónde encaja naturalmente en el flujo de trabajo.
¿Qué es la API de Firebase y por qué es importante?
Firebase no es una única API. Es un conjunto de servicios de backend a los que accedes vía SDKs unificados y puntos finales REST.
Servicios Principales de Firebase
| Servicio | Propósito | Tipo de API |
|---|---|---|
| Authentication | Inicio de sesión e identidad de usuario | SDK + REST |
| Firestore Database | Base de datos de documentos NoSQL | SDK + REST |
| Realtime Database | Sincronización en tiempo real de JSON | SDK + REST |
| Cloud Storage | Almacenamiento de archivos y CDN | SDK + REST |
| Cloud Functions | Cómputo sin servidor | CLI de despliegue |
| Hosting | Alojamiento web estático | CLI de despliegue |
| Cloud Messaging | Notificaciones push | HTTP v1 API |
Cuándo Firebase Tiene Sentido
Usa Firebase si:
- Necesitas sincronización en tiempo real (chat, colaboración, actualizaciones en vivo)
- Quieres arquitectura sin servidor (sin gestión de infraestructura)
- Estás construyendo apps móviles o web (los SDKs manejan las diferencias)
- Requieres soporte sin conexión (SDKs cachean datos)
- Quieres autenticación integrada (Google, Apple, email, teléfono)
Evita Firebase si:
- Necesitas consultas relacionales complejas (opta por PostgreSQL)
- Tienes requisitos estrictos de residencia de datos (regiones limitadas)
- Necesitas SQL completo (Firestore tiene restricciones)
- El costo a escala importa más que la velocidad de desarrollo (autoalojamiento es más barato)
La Arquitectura de la API de Firebase
Firebase utiliza un enfoque híbrido:
┌─────────────────────────────────────────────────────────┐
│ Tu Aplicación │
├─────────────────────────────────────────────────────────┤
│ Firebase SDK (Cliente) │
│ - Maneja automáticamente los tokens de autenticación │
│ - Gestiona la caché sin conexión │
│ - Escuchas en tiempo real │
└─────────────────────────────────────────────────────────┘
│
│ HTTPS + WebSocket
▼
┌─────────────────────────────────────────────────────────┐
│ Backend de Firebase │
├──────────────┬──────────────┬──────────────┬────────────┤
│ Servicio │ Base de │ Servicio │ Tiempo de │
│ de Autent. │ Datos │ de Almac. │ Ejecución │
│ │ Firestore │ │ de Func. │
└──────────────┴──────────────┴──────────────┴────────────┘
Los SDK de cliente abstraen la capa HTTP. Cada operación es una llamada API REST autenticada con JWT.
Autenticación de Firebase: Configuración Completa
La autenticación es la integración esencial. Mal implementada, nada más funciona.
Paso 1: Crear Proyecto de Firebase
- Ve a la Consola de Firebase
- Haz clic en "Agregar proyecto", elige un nombre (sin espacios)
- Habilita Google Analytics (opcional pero recomendado)
- Haz clic en "Crear proyecto" y espera el aprovisionamiento
Paso 2: Registrar Tu Aplicación
Web:
// En la Consola de Firebase > Configuración del Proyecto > General
// Haz clic en "Agregar aplicación" > Icono web
const firebaseConfig = {
apiKey: "AIzaSyDxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "tu-app.firebaseapp.com",
projectId: "tu-app",
storageBucket: "tu-app.appspot.com",
messagingSenderId: "123456789012",
appId: "1:123456789012:web:abc123def456"
};
import { initializeApp } from 'firebase/app';
const app = initializeApp(firebaseConfig);
iOS:
Descarga GoogleService-Info.plist y agrégalo al proyecto Xcode.
Android:
Descarga google-services.json y colócalo en app/. Añade a build.gradle:
// build.gradle a nivel de proyecto
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
// build.gradle a nivel de aplicación
plugins {
id 'com.google.gms.google-services'
}
Paso 3: Habilitar Métodos de Autenticación
En la Consola de Firebase > Autenticación > Método de inicio de sesión:
- Correo electrónico/Contraseña: Habilítalo para registro tradicional
- Google: Agrega SHA-1 (Android) o ID de paquete (iOS)
- Apple: Obligatorio en iOS si usas sociales
- Teléfono: Habilita para SMS (requiere facturación)
Paso 4: Implementar Flujo de Autenticación
Registro con correo/contraseña:
import {
createUserWithEmailAndPassword,
getAuth,
updateProfile
} from 'firebase/auth';
const auth = getAuth(app);
async function signUp(email, password, displayName) {
try {
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
await updateProfile(userCredential.user, { displayName });
console.log('Usuario creado:', userCredential.user.uid);
return userCredential.user;
} catch (error) {
switch (error.code) {
case 'auth/email-already-in-use':
throw new Error('Este correo electrónico ya está registrado');
case 'auth/weak-password':
throw new Error('La contraseña debe tener al menos 6 caracteres');
case 'auth/invalid-email':
throw new Error('Dirección de correo electrónico inválida');
default:
throw new Error('Fallo al registrarse: ' + error.message);
}
}
}
Inicio de sesión con correo/contraseña:
import {
signInWithEmailAndPassword,
signOut
} from 'firebase/auth';
async function signIn(email, password) {
try {
const userCredential = await signInWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
const idToken = await user.getIdToken();
console.log('Token de autenticación:', idToken);
return user;
} catch (error) {
switch (error.code) {
case 'auth/user-not-found':
throw new Error('No existe cuenta con este correo electrónico');
case 'auth/wrong-password':
throw new Error('Contraseña incorrecta');
case 'auth/too-many-requests':
throw new Error('Demasiados intentos. Inténtalo de nuevo más tarde');
default:
throw new Error('Fallo al iniciar sesión');
}
}
}
async function logOut() {
await signOut(auth);
console.log('Usuario cerró sesión');
}
Inicio de sesión con Google (Web):
import {
GoogleAuthProvider,
signInWithPopup
} from 'firebase/auth';
async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
provider.addScope('email');
provider.addScope('profile');
try {
const result = await signInWithPopup(auth, provider);
const user = result.user;
const credential = GoogleAuthProvider.credentialFromResult(result);
const googleAccessToken = credential.accessToken;
return user;
} catch (error) {
if (error.code === 'auth/popup-closed-by-user') {
throw new Error('Inicio de sesión cancelado');
}
throw new Error('Fallo en el inicio de sesión con Google');
}
}
Paso 5: Proteger Rutas con el Estado de Autenticación
import { onAuthStateChanged } from 'firebase/auth';
onAuthStateChanged(auth, (user) => {
if (user) {
console.log('Usuario:', user.email);
window.location.href = '/dashboard';
} else {
console.log('Ningún usuario');
window.location.href = '/login';
}
});
Errores Comunes de Autenticación
Error 1: No manejar la actualización del token
Los tokens expiran tras 1 hora. No los caches en el backend; verifica en cada solicitud.
Error 2: Exponer credenciales de administrador en el cliente
Jamás uses claves de cuenta de servicio en frontend. Solo en servidores confiables.
Error 3: Omitir verificación de correo electrónico
import { sendEmailVerification } from 'firebase/auth';
async function sendVerificationEmail(user) {
await sendEmailVerification(user);
console.log('Correo electrónico de verificación enviado');
}
if (!auth.currentUser.emailVerified) {
console.log('Correo electrónico no verificado');
// Restringir acceso
}
Base de Datos Firestore: Operaciones y Consultas
Firestore es la base de datos NoSQL de Firebase. Estructura: colecciones → documentos → subcolecciones.
Estructura de Datos
tu-proyecto (raíz)
└── users (colección)
├── userId123 (documento)
│ ├── name: "John"
│ ├── email: "john@example.com"
│ └── posts (subcolección)
│ ├── postId1 (documento)
│ └── postId2 (documento)
└── userId456 (documento)
Inicializar Firestore
import { getFirestore } from 'firebase/firestore';
const db = getFirestore(app);
Crear Documentos
import {
collection,
addDoc,
setDoc,
doc
} from 'firebase/firestore';
// ID autogenerado
async function createUser(userData) {
const docRef = await addDoc(collection(db, 'users'), userData);
console.log('Documento escrito con ID:', docRef.id);
return docRef.id;
}
// ID personalizado
async function createUserWithId(userId, userData) {
await setDoc(doc(db, 'users', userId), userData);
console.log('Documento escrito con ID personalizado:', userId);
}
// Uso
const userId = await createUser({
name: 'Alice',
email: 'alice@example.com',
createdAt: new Date(),
role: 'user'
});
Leer Documentos
import {
getDoc,
getDocs,
query,
where,
orderBy,
limit
} from 'firebase/firestore';
// Un documento
async function getUser(userId) {
const docRef = doc(db, 'users', userId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) return docSnap.data();
throw new Error('Usuario no encontrado');
}
// Consulta filtrada
async function getUsersByRole(role) {
const q = query(
collection(db, 'users'),
where('role', '==', role),
orderBy('createdAt', 'desc'),
limit(10)
);
const querySnapshot = await getDocs(q);
const users = [];
querySnapshot.forEach((doc) => {
users.push({ id: doc.id, ...doc.data() });
});
return users;
}
// Uso
const adminUsers = await getUsersByRole('admin');
console.log('Usuarios administradores:', adminUsers);
Actualizar Documentos
import {
updateDoc,
increment,
arrayUnion,
arrayRemove
} from 'firebase/firestore';
async function updateUser(userId, updates) {
const userRef = doc(db, 'users', userId);
await updateDoc(userRef, updates);
}
// Operaciones atómicas
await updateUser('userId123', {
loginCount: increment(1),
tags: arrayUnion('premium', 'beta-tester'),
lastLogin: new Date()
});
// Eliminar de una matriz
await updateUser('userId123', {
tags: arrayRemove('beta-tester')
});
Eliminar Documentos
import { deleteDoc } from 'firebase/firestore';
async function deleteUser(userId) {
await deleteDoc(doc(db, 'users', userId));
console.log('Usuario eliminado');
}
Escuchas en Tiempo Real
import { onSnapshot } from 'firebase/firestore';
// Documento individual
const unsubscribe = onSnapshot(
doc(db, 'users', userId),
(doc) => {
console.log('Usuario actualizado:', doc.data());
},
(error) => {
console.error('Error de escucha:', error);
}
);
// Consulta
const q = query(collection(db, 'posts'), where('published', '==', true));
const unsubscribeQuery = onSnapshot(q, (snapshot) => {
const posts = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
console.log('Publicaciones publicadas:', posts);
});
// Dejar de escuchar
unsubscribe();
unsubscribeQuery();
Reglas de Seguridad de Firestore
Configura reglas para proteger datos en la Consola de Firebase > Firestore > Reglas:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return request.auth.uid == userId;
}
match /users/{userId} {
allow read: if isAuthenticated();
allow create: if isAuthenticated() && isOwner(userId);
allow update, delete: if isOwner(userId);
}
match /posts/{postId} {
allow read: if true; // Lectura pública
allow create: if isAuthenticated();
allow update, delete: if resource.data.authorId == request.auth.uid;
}
match /users/{userId}/private/{document} {
allow read, write: if isOwner(userId);
}
}
}
Limitaciones de Consulta
Firestore limita:
-
No consultas OR (usa
ino combina en cliente) - No búsquedas wildcard (usa Algolia/Meilisearch)
- Consultas compuestas requieren índices
-
Límite de 30 disyunciones en
in
Ejemplo de consulta OR en cliente:
const activeQuery = query(
collection(db, 'tasks'),
where('status', '==', 'active')
);
const pendingQuery = query(
collection(db, 'tasks'),
where('status', '==', 'pending')
);
const [activeSnap, pendingSnap] = await Promise.all([
getDocs(activeQuery),
getDocs(pendingQuery)
]);
// Fusionar resultados en el cliente
Cloud Functions: Lógica de Backend sin Servidor
Cloud Functions ejecuta lógica backend sin servidores. Útil para activadores de base de datos, HTTP y tareas programadas.
Configuración
npm install -g firebase-tools
firebase login
firebase init functions
# Selecciona: JavaScript, ESLint sí, Express.js no
Funciones HTTP (Puntos Finales de API)
// functions/index.js
const { onRequest } = require('firebase-functions/v2/https');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
// Público
exports.getPublicData = onRequest(async (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
try {
const snapshot = await db.collection('public').get();
const data = snapshot.docs.map(doc => doc.data());
res.json({ success: true, data });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Protegido (token JWT)
exports.getUserProfile = onRequest(async (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
const authHeader = req.headers.authorization || '';
const token = authHeader.split('Bearer ')[1];
if (!token) {
return res.status(401).json({ error: 'No autorizado' });
}
try {
const decodedToken = await admin.auth().verifyIdToken(token);
const userId = decodedToken.uid;
const userDoc = await db.collection('users').doc(userId).get();
if (!userDoc.exists) {
return res.status(404).json({ error: 'Usuario no encontrado' });
}
res.json({
success: true,
data: { id: userId, ...userDoc.data() }
});
} catch (error) {
res.status(401).json({ error: 'Token inválido' });
}
});
Desplegar:
firebase deploy --only functions:getUserProfile
Consumir desde el cliente:
async function getUserProfile(token) {
const response = await fetch(
'https://us-central1-tu-app.cloudfunctions.net/getUserProfile',
{
headers: {
'Authorization': `Bearer ${token}`
}
}
);
const data = await response.json();
return data;
}
Disparadores de Base de Datos
const { onDocumentWritten } = require('firebase-functions/v2/firestore');
// Cuando el usuario cambia
exports.onUserUpdate = onDocumentWritten(
'users/{userId}',
async (event) => {
const userId = event.params.userId;
const before = event.data?.before?.data();
const after = event.data?.after?.data();
if (before?.email !== after?.email) {
console.log(`El correo electrónico del usuario ${userId} cambió: ${before?.email} → ${after?.email}`);
// Agrega lógica de notificación
}
}
);
// Nueva publicación creada
exports.onNewPost = onDocumentWritten(
'posts/{postId}',
async (event) => {
const post = event.data?.after?.data();
if (!post) return; // Documento eliminado
if (!event.data?.before?.exists) {
console.log('Nueva publicación creada:', post.title);
const followersSnap = await admin.firestore()
.collection('users')
.where('following', 'array-contains', post.authorId)
.get();
const notifications = followersSnap.docs.map(doc => ({
userId: doc.id,
postId: event.params.postId,
type: 'new_post',
createdAt: admin.firestore.FieldValue.serverTimestamp()
}));
const batch = admin.firestore().batch();
notifications.forEach(notif => {
const ref = admin.firestore().collection('notifications').doc();
batch.set(ref, notif);
});
await batch.commit();
}
}
);
Funciones Programadas (Trabajos Cron)
const { onSchedule } = require('firebase-functions/v2/scheduler');
// Cada día a medianoche UTC
exports.dailyCleanup = onSchedule('every 24 hours', async (event) => {
console.log('Ejecutando limpieza diaria');
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const oldNotifs = await admin.firestore()
.collection('notifications')
.where('createdAt', '<', thirtyDaysAgo)
.get();
const batch = admin.firestore().batch();
oldNotifs.forEach(doc => batch.delete(doc.ref));
await batch.commit();
console.log(`Eliminadas ${oldNotifs.size} notificaciones antiguas`);
});
Configuración de Entorno
# Setear variables
firebase functions:config:set \
stripe.secret="sk_test_xxx" \
email.api_key="key_xxx"
const config = require('firebase-functions/config');
const stripe = require('stripe')(config.stripe.secret);
Cloud Storage: Carga y Gestión de Archivos
Almacena cargas, imágenes y archivos con CDN.
Configurar Reglas de Almacenamiento
// Consola de Firebase > Storage > Reglas
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/{allPaths=**} {
allow read: if true; // Lectura pública
allow write: if request.auth.uid == userId;
allow delete: if request.auth.uid == userId;
}
match /public/{allPaths=**} {
allow read: if true;
allow write: if false;
}
}
}
Cargar Archivos (Cliente)
import {
getStorage,
ref,
uploadBytesResumable,
getDownloadURL
} from 'firebase/storage';
const storage = getStorage(app);
async function uploadProfileImage(userId, file) {
const storageRef = ref(storage, `users/${userId}/profile/${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file);
return new Promise((resolve, reject) => {
uploadTask.on(
'state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(`Carga: ${progress.toFixed(0)}%`);
},
(error) => {
switch (error.code) {
case 'storage/unauthorized':
reject(new Error('No tienes permiso'));
break;
case 'storage/canceled':
reject(new Error('Carga cancelada'));
break;
default:
reject(new Error('Fallo la carga'));
}
},
async () => {
const downloadURL = await getDownloadURL(uploadTask.snapshot.ref);
console.log('Archivo disponible en:', downloadURL);
resolve(downloadURL);
}
);
});
}
// Uso
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
if (file) {
const imageUrl = await uploadProfileImage(auth.currentUser.uid, file);
await updateDoc(doc(db, 'users', auth.currentUser.uid), {
profileImage: imageUrl
});
}
Descargar Archivos
import { getDownloadURL } from 'firebase/storage';
async function getProfileImage(userId) {
const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);
try {
const url = await getDownloadURL(imageRef);
return url;
} catch (error) {
if (error.code === 'storage/object-not-found') {
return null;
}
throw error;
}
}
Eliminar Archivos
import { deleteObject } from 'firebase/storage';
async function deleteProfileImage(userId) {
const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);
await deleteObject(imageRef);
console.log('Imagen de perfil eliminada');
}
Probando APIs de Firebase con Apidog
Firebase expone APIs REST para todos los servicios. Probarlos ayuda a depurar y entender las solicitudes.
Importar API REST de Firebase
- Abre Apidog
- Crea un proyecto: "Firebase API"
- Importa especificación OpenAPI o añade endpoints manualmente
Ejemplo Firestore REST:
POST https://firestore.googleapis.com/v1/projects/{projectId}/databases/(default)/documents
Authorization: Bearer {oauth2_token}
Content-Type: application/json
{
"fields": {
"name": { "stringValue": "John" },
"email": { "stringValue": "john@example.com" },
"age": { "integerValue": 30 }
}
}
Autenticación:
POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}
Content-Type: application/json
{
"email": "user@example.com",
"password": "secret123",
"returnSecureToken": true
}
Probar Flujo de Autenticación
- Crea solicitud "Iniciar Sesión"
- Método POST, cuerpo con email/contraseña
- Guarda el token de respuesta como variable de entorno
- Usa
{{token}}en peticiones siguientes
Depurar Reglas de Seguridad
Utiliza Firebase Emulator Suite:
firebase emulators:start
# Prueba contra http://localhost:8080
Mejores Prácticas de Producción
1. Manejo de Errores
async function firestoreWithRetry(operation, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await operation();
} catch (error) {
if (
error.code === 'unavailable' ||
error.code === 'deadline-exceeded'
) {
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
2. Optimizar Consultas
Agrega índices compuestos para consultas multifield:
const q = query(
collection(db, 'posts'),
where('category', '==', 'tech'),
where('views', '>', 1000),
orderBy('views', 'desc')
);
Firestore te pedirá crear el índice cuando sea necesario.
3. Operaciones por Lotes
import { writeBatch } from 'firebase/firestore';
async function bulkUpdate(userIds, updates) {
const batch = writeBatch(db);
userIds.forEach(id => {
const ref = doc(db, 'users', id);
batch.update(ref, updates);
});
await batch.commit();
console.log(`Actualizados ${userIds.length} usuarios`);
}
// Máximo 500 operaciones por lote
4. Monitorear Costos
| Servicio | Nivel Gratuito | De Pago |
|---|---|---|
| Firestore | 50K lecturas/día | $0.036/100K lecturas |
| Storage | 5GB | $0.023/GB |
| Functions | 2M invocaciones | $0.40/1M |
| Auth | 10K/mes | $0.0055/100K |
Configura alertas de presupuesto en Google Cloud Console.
5. Proteger Cuentas de Servicio
// MAL: No usar en frontend
admin.initializeApp({
credential: admin.credential.cert(require('./serviceAccountKey.json'))
});
// CORRECTO: Solo en servidores
const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
6. Manejar Sin Conexión
import { enableMultiTabIndexedDbPersistence } from 'firebase/firestore';
enableMultiTabIndexedDbPersistence(db)
.catch((err) => {
if (err.code === 'failed-precondition') {
// Múltiples pestañas abiertas
} else if (err.code === 'unimplemented') {
// El navegador no es compatible
}
});
import { onSnapshot } from 'firebase/firestore';
onSnapshot(doc(db, 'status', 'online'), (doc) => {
if (!doc.exists()) {
console.log('Estás sin conexión');
// Mostrar UI sin conexión
}
});
Problemas Comunes de la API de Firebase y Soluciones
Problema 1: Errores PERMISSION_DENIED
Síntoma: Error: 7 PERMISSION_DENIED
Solución:
- Verifica reglas en la consola
- Comprueba que
request.auth.uides correcto - Usa el Rules Playground
Problema 2: Expiración del Token
const user = auth.currentUser;
if (user) {
await user.getIdToken(true); // Forzar actualización
}
Problema 3: Latencia de Inicio en Frío
exports.keepWarm = onSchedule('every 60 seconds', async () => {
await fetch('https://tu-funcion.cloudfunctions.net/health');
});
Problema 4: Consulta Vacía
Causa: Falta índice o campos mal ordenados.
Solución: Revisa Firestore > Índices y crea los requeridos.
Casos de Uso en el Mundo Real
Fintech: Transacciones en Tiempo Real
Una startup de pagos usa Firestore y Cloud Functions para notificaciones instantáneas. Resultado: 40% menos tickets de soporte sobre transacciones "pendientes".
E-commerce: Sincronización de Inventario
Minoristas sincronizan stock entre web, iOS y Android con escuchas Firestore. La persistencia offline permite operaciones aún sin conectividad.
SaaS: Autenticación Multitenant
Una plataforma B2B usa Firebase Auth y reclamaciones personalizadas para roles, validando via Cloud Functions y Firestore. Más de 500 organizaciones, datos aislados.
Conclusión
La integración de la API de Firebase abarca:
- Autenticación: Login con email, Google, Apple, tokens JWT
- Firestore: NoSQL, escuchas en tiempo real, reglas de seguridad
- Cloud Functions: Backend serverless por eventos o HTTP
- Storage: Carga de archivos con CDN
Has visto flujos de autenticación, operaciones de base de datos, despliegue de funciones y gestión de archivos. Aplica patrones de producción: manejo de errores, procesamiento por lotes, soporte sin conexión y seguridad.
Preguntas Frecuentes
¿Es Firebase de uso gratuito?
Sí, Firebase tiene un nivel gratuito (Spark) con 5 GB de storage, 50K lecturas Firestore al día, 2M invocaciones Cloud Function y 10K usuarios Auth al mes. El plan Blaze es pago por uso.
¿Puedo usar Firebase con bases de datos existentes?
Sí. Usa Firebase Extensions para sincronizar con PostgreSQL, MySQL o MongoDB. O llama APIs externas desde Cloud Functions.
¿Cómo migro de Firebase a otra plataforma?
Exporta datos vía CLI o Firestore, usa Dataflow para grandes volúmenes. La dificultad depende de la estructura de tus datos.
¿Firebase soporta GraphQL?
No nativamente. Usa soluciones como firestore-graphql o crea una capa GraphQL con Cloud Functions y Apollo Server.
¿Puedo usar Firebase on-premise?
No. Firebase es solo para Google Cloud. Alternativas autoalojadas: Appwrite, Supabase, Nhost.
¿Cómo manejo cargas de archivos de más de 100 MB?
Usa cargas reanudables y fragmentadas (el SDK lo soporta). Para archivos muy grandes, usa Google Cloud Storage directamente con URLs firmadas.
¿Qué sucede si excedo los límites de consulta de Firestore?
Obtendrás error FAILED_PRECONDITION. Crea los índices requeridos o reestructura tus consultas. Firestore te da enlaces directos en el mensaje de error.
¿Firebase cumple con el GDPR?
Sí, es compatible con GDPR. Habilita residencia de datos, exportación/eliminación de usuarios y firma la Enmienda de Procesamiento de Datos de Google.
Top comments (0)