{}FireSchema

Firestore Best Practices: 15 Regeln, die jeder Entwickler kennen sollte

Datenmodellierung, Queries, Sicherheit und Kostenoptimierung für Firebase-Projekte

Du entwickelst mit Firestore? Diese 15 Regeln bewahren dich vor den häufigsten Fallstricken. Egal, ob du dein erstes Firebase-Projekt startest oder ein bestehendes skalierst, diese Best Practices decken alles ab — von Datenmodellierung bis Kostenoptimierung — gelernt aus echten Produktionsanwendungen.

Datenmodellierungs-Regeln

Wie du deine Daten strukturierst, bestimmt alles andere — Query-Performance, Kosten und Wartbarkeit. Das muss zuerst stimmen.

1. Bevorzuge flache Sammlungen statt tiefer Verschachtelung

Tief verschachtelte Untersammlungen erschweren Queries und erzeugen enge Kopplung. Halte deine Sammlungshierarchie flach — normalerweise 1-2 Ebenen tief. Nutze Root-Level-Sammlungen mit Dokumentreferenzen, anstatt alles unter einem Parent zu verschachteln. Speichere zum Beispiel orders als Root-Sammlung mit einem userId-Feld, anstatt unter users/{id}/orders zu verschachteln — außer du fragst Bestellungen nur nach Benutzer ab.

2. Denormalisiere Daten für Lese-Performance

In SQL normalisierst du, um Duplikation zu vermeiden. In Firestore denormalisierst du, um mehrfache Lesevorgänge zu vermeiden. Wenn deine Oberfläche einen Benutzernamen neben jedem Kommentar anzeigt, speichere authorName direkt in jedem Kommentar-Dokument — erzwinge keinen separaten Lesevorgang zur Benutzersammlung. Akzeptiere den Kompromiss: Schreibvorgänge sind komplexer, aber Lesevorgänge sind schnell und günstig.

3. Nutze Untersammlungen für unbegrenzte Eins-zu-Viele-Beziehungen

Wenn ein Dokument Hunderte oder Tausende verwandter Elemente haben kann (Nachrichten in einem Chat, Bestellungen für einen Benutzer), nutze Untersammlungen. Im Gegensatz zu Arrays innerhalb von Dokumenten können Untersammlungen unbegrenzt viele Elemente enthalten und unterstützen effiziente Queries mit Paginierung. Beispiel: chats/{chatId}/messages/{messageId}.

4. Halte Dokumente unter 20 KB für optimale Performance

Firestores harte Grenze liegt bei 1 MB pro Dokument, aber strebe unter 20 KB an. Große Dokumente verschwenden Bandbreite, wenn du nur einige Felder brauchst — und Firestore berechnet pro Dokumentlesevorgang unabhängig von der Größe. Wenn ein Dokument wächst, teile es in Untersammlungen oder eine separate Sammlung auf.

5. Vermeide Arrays für abfragbare Daten

Arrays in Firestore haben Einschränkungen: Du kannst einzelne Elemente nicht aktualisieren, array-contains-Queries unterstützen nur eines pro Query, und Arrays skalieren schlecht über einige hundert Elemente hinaus. Für Tags oder Kategorien nutze array-contains, aber für Beziehungen oder wachsende Listen verwende stattdessen Untersammlungen oder Map-Felder.

Query-Optimierung

Firestore-Queries sind von Natur aus schnell, aber nur wenn du mit ihren Beschränkungen arbeitest — nicht gegen sie.

6. Erstelle Composite-Indizes proaktiv

Firestore benötigt einen Index für jedes eindeutige Query-Muster. Anstatt auf Fehlermeldungen zu warten, plane deine Indizes im Voraus. Definiere sie in firestore.indexes.json und deploye mit firebase deploy --only firestore:indexes. Jede where + orderBy-Kombination braucht ihren eigenen Composite-Index.

7. Nutze Cursor-basierte Paginierung, keine Offsets

Verwende niemals Offset-basierte Paginierung in Firestore — es liest (und berechnet) trotzdem alle übersprungenen Dokumente. Nutze stattdessen startAfter() mit dem letzten Dokument der vorherigen Seite. Das ist sowohl schneller als auch günstiger, da Firestore nur die Dokumente liest, die du tatsächlich brauchst.

8. Begrenze Query-Ergebnisse explizit

Füge immer .limit() zu deinen Queries hinzu. Ohne gibt Firestore jedes passende Dokument zurück — das könnten Millionen sein. Selbst wenn du denkst, eine Sammlung ist heute klein, wird sie es in sechs Monaten nicht mehr sein. Ein guter Standard ist 20-50 Dokumente pro Query.

9. Vermeide das Lesen ganzer Sammlungen

Wenn du collection('users').get() ohne Filter ausführst, braucht dein Datenmodell Überarbeitung. Nutze Aggregations-Queries (count(), sum()) für Analytics und filtere immer mit where() für Anzeige-Queries. Das Lesen aller Dokumente ist die Hauptursache für unerwartete Firestore-Rechnungen.

Security Rules-Muster

Firestore Security Rules sind deine einzige serverseitige Validierung. Wenn sie falsch sind, ist deine gesamte Datenbank exponiert.

10. Validiere immer Feldtypen in Rules

Prüfe nicht nur, ob ein Feld existiert — validiere seinen Typ. Ein böswilliger Client könnte age: "not a number" senden, wenn du nur request.resource.data.age != null prüfst. Nutze is string, is number, is bool, um Typen auf Security-Rules-Ebene zu erzwingen.

11. Nutze granulare Pro-Sammlung-Rules

Verwende niemals allow read, write: if true auf Datenbankebene. Schreibe spezifische Rules für jede Sammlung: wer darf lesen, wer darf erstellen, wer darf aktualisieren, wer darf löschen. Beginne mit allem verweigert und öffne Zugriff schrittweise. Nutze match-Muster für Untersammlungen.

12. Vertraue niemals clientseitigen Daten

Der Client kann beliebige Daten senden. Validiere erforderliche Felder, prüfe Datentypen, erzwinge Enum-Werte und verifiziere, dass Referenzfelder auf echte Dokumente zeigen. Nutze request.auth, um zu verifizieren, dass der Benutzer der ist, der er vorgibt zu sein, und resource.data zum Vergleich mit bestehenden Werten.

Kostenoptimierung

Firestore-Preise basieren auf Reads, Writes und Storage. Kleine Änderungen bei Queries können große Auswirkungen auf deine Rechnung haben.

13. Bündle Writes, um Operationen zu reduzieren

Nutze writeBatch() oder runTransaction(), um mehrere Writes in eine einzige Operation zu kombinieren. Ein Batch von 500 Writes kostet dasselbe wie 500 einzelne Writes hinsichtlich Operationen, reduziert aber Netzwerk-Roundtrips und gewährleistet Atomarität. Begrenze Batches auf maximal 500 Operationen.

14. Cache häufig gelesene Dokumente

Firestores Client-SDK hat eingebaute Offline-Persistenz — aktiviere sie. Für serverseitige Anwendungen implementiere eine Cache-Schicht (Redis, in-memory) für Dokumente, die sich selten ändern, aber ständig gelesen werden, wie App-Konfiguration oder Benutzerprofile. Jeder gecachte Lesevorgang ist ein Lesevorgang, für den du nicht zahlst.

15. Nutze Aggregations-Queries statt alle Dokumente zu lesen

Brauchst du eine Dokumentenanzahl? Nutze countQuery() statt alle Dokumente zu holen und clientseitig zu zählen. Firestore-Aggregations-Queries (count(), sum(), average()) lesen Index-Einträge statt volle Dokumente und kosten ungefähr 1/1000 pro Eintrag.

Bonus: Dokumentiere deine Datenbankstruktur

All diese Best Practices sind nutzlos, wenn dein Team sie nicht finden kann. Wenn deine Firestore-Datenbank wächst, wird es zur Herausforderung, Sammlungsstrukturen, Feldtypen und Validierungsregeln im Blick zu behalten. JSON Schema gibt dir eine standardisierte Weise, deine Datenbankstruktur zu beschreiben — und Tools wie FireSchema verwandeln diese Schemas in interaktive, durchsuchbare Dokumentation, die dein ganzes Team als Referenz nutzen kann.

💡 Tipp: Erstelle eine .schema.json-Datei für jede Sammlung, die ihre Felder, Typen und Validierungsregeln dokumentiert. Das wird zur Single Source of Truth deines Teams.

Nächste Schritte

Lerne weiter über Firestore und Datenbankdokumentation:

FireSchema ausprobieren

Schnellstart-Anleitung