← Назад к вопросам

Расскажи про свой опыт работы с Firebase

1.0 Junior🔥 151 комментариев
#Опыт и проекты#Инструменты аналитика

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Опыт работы с Firebase: практические кейсы

Введение

Файрбэйс — это платформа Google для быстрой разработки приложений без мощного backend. За 10+ лет я работал с Firebase в 8+ проектах. Это не всегда был хороший выбор, но когда он подходит — это магия.

Когда я использовал Firebase

  1. Startup с MVP (2 проекта)

    • Нужно быстро вывести на рынок
    • Нет бюджета на backend разработчиков
    • Firebase идеален
  2. Real-time приложение (2 проекта)

    • Chat, notifications, live updates
    • Realtime Database / Firestore
    • Встроенное решение
  3. Mobile-first проект (2 проекта)

    • iOS/Android приложения
    • Analytics, Crashlytics
    • Native Firebase integration
  4. Один большой проект, где это был ошибка

    • Outgrew Firebase за год
    • Дорого, неэластично
    • Пришлось мигрировать

Case 1: Startup с MVP на Firebase (3 месяца)

Ситуация: Стартап: приложение для планирования фитнеса. 2 разработчика, бюджет $20k.

Выбор: Firebase вместо custom backend

Вариант 1: Custom backend

  • Setup: Node.js + Express + PostgreSQL
  • Infrastructure: DigitalOcean/AWS
  • Time: 4 недели
  • Cost: $15k
  • Risk: нужен DevOps, большой overhead

Вариант 2: Firebase

  • Setup: Google Firebase console
  • Infrastructure: managed Google
  • Time: 1 неделя
  • Cost: $0-5k (зависит от usage)
  • Risk: low

Выбрал Firebase.

Architecture на Firebase:

Frontend (React + Firebase SDK)
    ├─ Authentication
    │  └─ Firebase Auth (email/password, Google Sign-In)
    │
    ├─ Database
    │  └─ Firestore (NoSQL document store)
    │
    ├─ Storage
    │  └─ Firebase Storage (file uploads - фото профиля, workout images)
    │
    ├─ Functions
    │  └─ Cloud Functions (calculate stats, send email)
    │
    └─ Analytics
       └─ Google Analytics for Firebase

Data Model на Firestore:

users/
  {userId}/
    ├─ email: "john@example.com"
    ├─ name: "John"
    ├─ createdAt: timestamp
    └─ settings:
        ├─ notifications: true
        └─ theme: "dark"

workouts/
  {workoutId}/
    ├─ userId: "{userId}"
    ├─ date: timestamp
    ├─ type: "cardio"
    ├─ duration: 45 (minutes)
    ├─ calories: 400
    └─ notes: "Great session!"

friends/
  {userId}/{friendUserId}/
    ├─ addedAt: timestamp
    └─ status: "confirmed"

Rules (Security & Access Control):

// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Users can read/write only their own data
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
    
    // Workouts: user can read/write their own
    match /workouts/{workoutId} {
      allow read, write: if request.auth.uid == resource.data.userId;
    }
    
    // Friends: can see friend's workouts if they're friends
    match /workouts/{workoutId} {
      allow read: if isFriend(request.auth.uid, resource.data.userId);
    }
  }
  
  function isFriend(user1, user2) {
    return exists(/databases/$(database)/documents/friends/$(user1)/$(user2));
  }
}

Cloud Functions (для backend logic):

// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp();

// Trigger: когда пользователь создаёт workout
exports.onWorkoutCreated = functions.firestore
  .document('workouts/{workoutId}')
  .onCreate(async (snap, context) => {
    const workout = snap.data();
    const userId = workout.userId;
    
    // 1. Update user stats
    const userRef = admin.firestore().collection('users').doc(userId);
    await userRef.update({
      totalWorkouts: admin.firestore.FieldValue.increment(1),
      totalCalories: admin.firestore.FieldValue.increment(workout.calories)
    });
    
    // 2. Notify friends
    const friendsRef = admin.firestore()
      .collection('friends')
      .doc(userId);
    
    const friends = await friendsRef.collection('friends').get();
    
    for (const friend of friends.docs) {
      // Send notification (Firebase Cloud Messaging)
      await admin.messaging().sendToDevice(
        friend.data().fcmToken,
        {
          notification: {
            title: `${workout.type} workout`,
            body: `${workout.duration} minutes, ${workout.calories} calories`
          }
        }
      );
    }
  });

// Trigger: delete user data when account deleted
exports.onUserDeleted = functions.auth
  .user()
  .onDelete(async (user) => {
    await admin.firestore().collection('users').doc(user.uid).delete();
    // Delete all his workouts
    const workouts = await admin.firestore()
      .collection('workouts')
      .where('userId', '==', user.uid)
      .get();
    
    const batch = admin.firestore().batch();
    workouts.docs.forEach(doc => batch.delete(doc.ref));
    await batch.commit();
  });

Frontend code:

// React component
import { getFirestore, collection, addDoc } from 'firebase/firestore';

const LogWorkout = () => {
  const [loading, setLoading] = useState(false);
  
  const handleSubmit = async (data) => {
    setLoading(true);
    try {
      const db = getFirestore();
      const user = auth.currentUser;
      
      await addDoc(collection(db, 'workouts'), {
        userId: user.uid,
        date: new Date(),
        type: data.type,
        duration: data.duration,
        calories: data.calories,
        notes: data.notes
      });
      
      // Show success
      setLoading(false);
    } catch (error) {
      console.error('Error:', error);
      // Show error
    }
  };
  
  return (
    // Form JSX
  );
};

Результат:

  • MVP готов за 8 недель (вместо 12)
  • Launched на App Store / Play Store
  • First 1000 users на Firebase
  • Cost: $150/месяц (очень дёшево на этом scale'е)
  • Стартап получил $500k funding

Case 2: Масштабирование и миграция с Firebase (6 месяцев)

Ситуация: Стартап выше вырос до 100k active users. Firebase стал дороговато и inflexible.

Проблемы с Firebase:

1. COST escalation
   10k users: $150/месяц (дёшево)
   100k users: $2500/месяц (дорого!)
   1M users: $25k/месяц (очень дорого)
   
   Расчёт:
   - Firestore: $0.06 за 100k reads
   - 100k users, каждый делает 100 reads/день
   = 10M reads/день = 300M reads/месяц
   = $1800/месяц только на reads

2. LIMITED QUERYING
   Firebase не поддерживает:
   - Complex aggregations
   - Arbitrary joins
   - Full-text search
   - Custom analytics

3. VENDOR LOCK-IN
   - Hard to migrate out
   - Custom optimizations сложны
   - Limited control over data

4. PERFORMANCE
   - N+1 query problem
   - Bandwidth-heavy
   - Limited caching control

Decision: Migrate to custom backend

My migration plan (6 месяцев):

Phase 1: Duplicate data (4 недели)

Одновременно пишем в обе системы:

Frontend
    |
    +-> Firebase (старая система)
    |
    +-> Custom backend (новая система)
// Write to both
const addWorkout = async (data) => {
  // Firebase
  await addDoc(collection(db, 'workouts'), data);
  
  // Custom backend
  await fetch('https://api.myapp.com/workouts', {
    method: 'POST',
    body: JSON.stringify(data)
  });
};

Phase 2: Validate data (2 недели)

Daily job:
1. Count records в Firebase
2. Count records в custom backend
3. Compare sample records
4. Если match → OK, если не match → investigate

Результат: 100% data consistency

Phase 3: Read traffic migration (4 недели)

Сначала читаем из Firebase:
if (useNewBackend) {
  data = await fetch('https://api.myapp.com/...');
} else {
  data = await getFirestoreData(...);
}

Гдалось slowly rolling out новый backend:
- Day 1: 10% users на new backend
- Day 5: 50% users
- Day 10: 100% users

Мониторим:
- Performance: новый backend быстрее
- Errors: если есть, откатываемся

Phase 4: Decommission Firebase (1 неделя)

Когда 100% пользователей на new backend:
1. Stop writing to Firebase
2. Keep 3 месяца как backup
3. Validate all data migrated
4. Delete Firebase data

Cost impact:

  • Firebase: $2500/месяц → $0
  • Custom backend: $0 → $800/месяц (сервер + БД)
  • Net savings: $1700/месяц!

Case 3: Real-time Chat на Firebase (perfect use case)

Ситуация: Б2Б SaaS app. Нужна real-time коммуникация между team members.

Firebase идеален для этого!

Архитектура:

User A                    Firebase Realtime DB              User B
  |                                |                          |
  +---write message---------+      |                          |
                             |      |                          |
                      realtime sync |                          |
                             |      |---update listener------>|
                             |                                  |
                             |      |<----write reply----------+
                             |      |
                        realtime sync
                             |      |
                        +----+      |
                        |           v
                       Message persisted
                       in Firestore

Data structure:

chats/
  {teamId}/
    {conversationId}/
      messages/
        {messageId}/
          ├─ text: "Hello"
          ├─ author: "john@"
          ├─ timestamp: 1234567890
          └─ read: false

Real-time listener:

const subscribeToMessages = (conversationId, callback) => {
  const messagesRef = ref(
    db, 
    `chats/myteam/${conversationId}/messages`
  );
  
  onValue(messagesRef, (snapshot) => {
    const messages = [];
    snapshot.forEach((childSnapshot) => {
      messages.push({
        id: childSnapshot.key,
        ...childSnapshot.val()
      });
    });
    callback(messages);
  });
};

// Usage
const [messages, setMessages] = useState([]);

useEffect(() => {
  const unsubscribe = subscribeToMessages(convId, setMessages);
  return unsubscribe; // cleanup
}, [convId]);

**Sent messages:

const sendMessage = async (text) => {
  const messageRef = push(
    ref(db, `chats/myteam/${convId}/messages`)
  );
  
  await set(messageRef, {
    text,
    author: user.email,
    timestamp: serverTimestamp(),
    read: false
  });
};

Преимущества Firebase для чата:

  • Realtime updates (no polling)
  • Easy to setup
  • Automatic persistence
  • Works offline
  • Scales well for small teams

Результат: Уда-то чатов реализовано за 2 недели. Использует Firebase 2+ года без проблем.

Best practices при использовании Firebase

1. Security Rules first

// ❌ BAD: Anyone can read anything
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true; // Dangerous!
    }
  }
}

// ✓ GOOD: Specific rules
match /users/{userId} {
  allow read, write: if request.auth.uid == userId;
}

2. Optimize queries

// ❌ BAD: Downloads entire collection
const all = await getDocs(collection(db, 'posts'));

// ✓ GOOD: Query with limits
const first10 = await getDocs(
  query(
    collection(db, 'posts'),
    where('published', '==', true),
    orderBy('createdAt', 'desc'),
    limit(10)
  )
);

3. Use indexes

// Firestore automatically creates single-field indexes
// But for compound queries, create composite indexes in console

// Example composite index needed:
const q = query(
  collection(db, 'posts'),
  where('userId', '==', uid),
  where('published', '==', true),
  orderBy('createdAt', 'desc')
);
// Firestore will prompt to create index

4. Batch writes for consistency

// ❌ BAD: 3 writes, potential inconsistency
await updateDoc(userRef, { points: currentPoints + 10 });
await updateDoc(leaderboardRef, { topScore: newScore });
await addDoc(collection(db, 'events'), { type: 'score_updated' });

// ✓ GOOD: Atomic batch
const batch = writeBatch(db);
batch.update(userRef, { points: currentPoints + 10 });
batch.update(leaderboardRef, { topScore: newScore });
batch.set(newEventRef, { type: 'score_updated' });
await batch.commit();

5. Pagination for large datasets

let lastVisible = null;

const loadMore = async () => {
  let q;
  
  if (!lastVisible) {
    q = query(
      collection(db, 'posts'),
      orderBy('createdAt', 'desc'),
      limit(20)
    );
  } else {
    q = query(
      collection(db, 'posts'),
      orderBy('createdAt', 'desc'),
      startAfter(lastVisible),
      limit(20)
    );
  }
  
  const docs = await getDocs(q);
  lastVisible = docs.docs[docs.docs.length - 1];
  return docs;
};

Когда Firebase НЕ подходит

  1. Complex analytics

    • Нужны агрегации, join'ы
    • Firebase слабый для этого
    • Используй PostgreSQL + BI tool
  2. Strict ACID транзакции

    • Firebase: eventual consistency
    • Bank transfers: нужен PostgreSQL
  3. Full-text search

    • Firebase не поддерживает
    • Используй Elasticsearch
  4. Large scale (>1M users)

    • Firebase становится дорого
    • Custom backend дешевле
  5. Need full control

    • Firebase: managed service
    • Custom: полный контроль

Вывод

Firebase — отличный инструмент для:

  • ✓ MVP с быстрым time-to-market
  • ✓ Real-time приложения (chat, notifications)
  • ✓ Mobile apps с analytics
  • ✓ Projects < 100k users

Но для:

  • ✗ Large-scale production
  • ✗ Complex queries
  • ✗ Cost-sensitive operations

Лучше custom backend.

Моя рекомендация: Стартуй с Firebase. Когда вырастешь — мигрируй на custom backend. Firebase спасает месяцы разработки на early stage.

Расскажи про свой опыт работы с Firebase | PrepBro