Firebase-interviewvragen 2026: Flutter Auth, Firestore en Security Rules
Firebase-interviewvragen voor Flutter-developers, met antwoorden in Dart: auth state streams, Google Sign-In v7, Firestore CRUD en datamodellering, security rules, custom claims, transacties en de wijzigingen in FlutterFire 5.

Firebase-interviewvragen voor Flutter-functies draaien om vijf onderwerpen: de drie auth state streams, datamodellering in Firestore, security rules, offline writes en het kostenmodel achter elke read. Firebase blijft in 2026 de standaardbackend voor Flutter-apps, en sinds oktober 2026 verschijnen de FlutterFire-plugins als BoM 5.x (firebase_core 5.1.0, firebase_auth 7.0.1, cloud_firestore 7.1.0), met een Android-minSdk die naar 24 is verhoogd en de Firebase Apple SDK 13 eronder.
De huidige FlutterFire-release is BoM 5.1.0: firebase_auth 7.0.1, cloud_firestore 7.1.0, firebase_core 5.1.0. De major 5.0.0 vereist Android-minSdk 24, bouwt op de Firebase Apple SDK 13.0.0 en hernoemt de activate-parameters van App Check. Firestore Pipelines, toegevoegd in cloud_firestore 6.3.0, krijgen bij elke release nieuwe expressies.
Firebase-interviewvragen: wat er in 2026 gevraagd wordt
Interviewers vragen zelden naar API-weetjes. Ze toetsen of een kandidaat begrijpt waar Firebase regels afdwingt, wat elke operatie kost en wat er gebeurt als het netwerk wegvalt. De tabel koppelt de terugkerende onderwerpen aan wat een sterk antwoord moet bevatten. Elk onderwerp wordt verderop uitgebreid beantwoord in de sectie Firebase-interviewvragen voor Flutter-developers.
| Onderwerp | Typische vraag | Wat een sterk antwoord bevat |
|---|---|---|
| Auth streams | authStateChanges() vs idTokenChanges() vs userChanges() | Welke events elke stream uitzendt, en welke de navigatie bewaakt |
| Beveiliging | Waar wordt toegangscontrole afgedwongen? | Security rules op de server, nooit checks in de client; App Check is een andere laag |
| Rollen | Hoe implementeer je een adminrol? | Custom claims gezet via de Admin SDK, gelezen via request.auth.token |
| Datamodellering | Modelleer een chat-app | Subcollections, gedenormaliseerd laatste bericht, één document per bericht |
| Consistentie | Transactie of batched write? | Transacties lezen, schrijven daarna en worden opnieuw geprobeerd; batches schrijven alleen, atomair |
| Offline | Wat gebeurt er met een write zonder netwerk? | Lokale cache, hasPendingWrites, synchronisatie bij herverbinding |
| Kosten | Waarom is dit scherm duur? | Facturering per gelezen document, listeners, paginering met cursors |
| Vergelijking | Firestore vs Realtime Database | Querymodel, schaalbaarheid, factureringseenheid |
Firebase Project Setup en Initialisatie
De eerste stap bij elke Firebase-integratie is het configureren van het Firebase project en het initialiseren van de SDK in de Flutter app. Sinds FlutterFire CLI v0.3 is dit proces aanzienlijk vereenvoudigd.
Developers gebruiken flutterfire configure om automatisch platform-specifieke configuratiebestanden te genereren. Dit commando maakt een firebase_options.dart bestand aan met alle benodigde API keys en project identifiers voor iOS, Android en Web.
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase with platform-specific config
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}De ensureInitialized() methode garandeert dat de Flutter engine volledig is opgestart voordat asynchrone Firebase-initialisatie plaatsvindt. De currentPlatform getter selecteert automatisch de juiste configuratie op basis van het draaiende platform.
Flutter apps kunnen meerdere Firebase projects gebruiken via Firebase.initializeApp(name: 'secondary', options: ...). Dit is nuttig voor apps die verschillende environments (development, staging, production) ondersteunen binnen dezelfde build.
Email/Password Authenticatie met FirebaseAuth
De firebase_auth package biedt een declaratieve API voor gebruikersbeheer, met email/password, OAuth-providers (Google, Apple, GitHub), sms-verificatie en multi-factor authenticatie, sinds firebase_auth 6.1.0 ook TOTP op macOS. De AuthService class kapselt alle authenticatielogica in en biedt foutafhandeling voor veelvoorkomende scenario's.
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Register with email and password
Future<User?> register(String email, String password) async {
try {
final credential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
} on FirebaseAuthException catch (e) {
// Handle specific error codes
switch (e.code) {
case 'email-already-in-use':
throw Exception('This email is already registered');
case 'weak-password':
throw Exception('Password must be at least 6 characters');
default:
throw Exception('Registration failed: ${e.message}');
}
}
}
// Sign in with existing credentials
Future<User?> signIn(String email, String password) async {
final credential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
}
// Reactive auth state stream
Stream<User?> get authStateChanges => _auth.authStateChanges();
}De authStateChanges() stream is de hoeksteen van reactieve authenticatie in Flutter. Widgets kunnen deze stream gebruiken met StreamBuilder om automatisch te reageren op login/logout events zonder handmatige state management.
Wachtwoordregels hoeven niet langer alleen in de client te staan: de validatePassword-API (beschikbaar sinds firebase_auth 6.0.0) toetst een wachtwoord aan het beleid dat in de Firebase Console is ingesteld, dat een minimale lengte, hoofdletters, kleine letters, cijfers en speciale tekens kan vereisen.
Google Sign-In Integratie
OAuth providers zoals Google vereisen een extra package. Sinds google_sign_in 7.0 is de plugin een singleton die via GoogleSignIn.instance wordt opgehaald, precies één keer moet worden geïnitialiseerd, en authenticatie staat los van autorisatie. De aanroep GoogleSignIn().signIn() uit oudere tutorials compileert niet meer.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
// Call once at startup, before any other GoogleSignIn method
Future<void> initGoogleSignIn() => GoogleSignIn.instance.initialize();
Future<UserCredential> signInWithGoogle() async {
try {
// Shows the native account picker; throws if the user cancels
final googleUser = await GoogleSignIn.instance.authenticate();
// Synchronous getter since v7: only the ID token is exposed here
final googleAuth = googleUser.authentication;
// Firebase only needs the ID token to create the credential
final credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
);
return FirebaseAuth.instance.signInWithCredential(credential);
} on GoogleSignInException catch (e) {
if (e.code == GoogleSignInExceptionCode.canceled) {
throw Exception('Sign-in cancelled');
}
rethrow;
}
}Deze methode demonstreert de credential exchange flow: Google tokens worden omgezet naar een Firebase credential die vervolgens wordt gebruikt voor authenticatie. Dit patroon is identiek voor andere OAuth providers zoals Apple, Facebook en Microsoft. Moet de app ook een Google-API aanroepen (Drive, Calendar), dan komt het access token nu uit een aparte stap, authorizationClient.authorizeScopes, zoals beschreven in de migratiegids van google_sign_in.
Een kandidaat die GoogleSignIn().signIn() schrijft en accessToken uit authentication leest, citeert de API van vóór 7.0. In v7 geeft authenticate() het account terug, bevat authentication alleen nog het idToken, en vereisen access tokens voor extra scopes een expliciete autorisatie-aanroep.
Google Sign-In op iOS vereist een geconfigureerde URL scheme in Info.plist. De FlutterFire documentatie bevat platform-specifieke setup guides die deze stappen in detail uitleggen.
Firestore CRUD Operaties met Cloud Firestore
Cloud Firestore is een NoSQL document database die realtime synchronisatie en offline persistence ondersteunt. De cloud_firestore package biedt een type-safe API voor alle database operaties.
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskService {
final _db = FirebaseFirestore.instance;
final String _collection = 'tasks';
// Create a new document with auto-generated ID
Future<String> createTask(String userId, String title) async {
final doc = await _db.collection(_collection).add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
// Read a single document by ID
Future<Map<String, dynamic>?> getTask(String taskId) async {
final snapshot = await _db.collection(_collection).doc(taskId).get();
return snapshot.data();
}
// Update specific fields without overwriting the entire document
Future<void> toggleComplete(String taskId, bool completed) async {
await _db.collection(_collection).doc(taskId).update({
'completed': completed,
'updatedAt': FieldValue.serverTimestamp(),
});
}
// Delete a document
Future<void> deleteTask(String taskId) async {
await _db.collection(_collection).doc(taskId).delete();
}
}De FieldValue.serverTimestamp() methode garandeert consistente timestamps tussen clients met verschillende tijdzones. Firestore gebruikt deze server-side timestamps voor accurate ordering en synchronisatie. Sinds cloud_firestore 7.1.0 komen FieldValue.minimum en FieldValue.maximum bij de server-side transforms: ze bewaren de laagste of hoogste waarde van opgeslagen en inkomende waarde zonder voorafgaande read, wat past bij tellers zoals een topscore.
Realtime Synchronisatie met Snapshots
De kracht van Firestore ligt in realtime streams. De snapshots() methode retourneert een Stream die automatisch updates pushed wanneer data wijzigt.
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskStream {
final _db = FirebaseFirestore.instance;
// Stream all tasks for a specific user, ordered by creation date
Stream<List<Map<String, dynamic>>> userTasks(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) => snapshot.docs.map((doc) {
final data = doc.data();
data['id'] = doc.id; // Include document ID
return data;
}).toList());
}
}Deze stream kan direct worden gebruikt in een StreamBuilder widget. Elke keer dat een task wordt toegevoegd, gewijzigd of verwijderd, ontvangt de UI automatisch een update zonder polling of manual refresh.
Klaar om je Flutter gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Firestore Security Rules voor Productie
Firestore security rules vormen de eerste verdedigingslinie tegen ongeautoriseerde toegang. Deze declaratieve regels worden server-side afgedwongen en kunnen niet worden omzeild door gemanipuleerde client code.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can only access their own profile
match /users/{userId} {
allow read, update: if request.auth != null
&& request.auth.uid == userId;
allow create: if request.auth != null;
allow delete: if false; // Prevent self-deletion
}
// Tasks belong to the user who created them
match /tasks/{taskId} {
allow read, write: if request.auth != null
&& resource.data.userId == request.auth.uid;
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
}
}
}De request.auth variabele bevat de huidige gebruiker. De resource.data verwijst naar bestaande documenten, terwijl request.resource.data de inkomende data representeert bij create/update operaties.
De Firebase Console bevat een Rules Playground waar developers security rules kunnen testen met gesimuleerde requests. Dit is essentieel voor het voorkomen van data leaks in productie.
Offline Persistentie en Synchronisatie
Firestore ondersteunt automatische offline persistence. Writes worden lokaal in een cache opgeslagen en gesynchroniseerd zodra de netwerk connectie hersteld is.
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('tasks')
.doc(taskId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
final data = snapshot.data!;
final isPending = data.metadata.hasPendingWrites;
return Row(
children: [
Text(data['title']),
if (isPending) const Icon(Icons.cloud_upload, size: 16),
],
);
},
)De hasPendingWrites property geeft aan of een document lokale wijzigingen heeft die nog niet naar de server zijn gesynchroniseerd. Dit is cruciaal voor het tonen van accurate loading states in de UI.
Cache Configuratie
Developers kunnen de cache size en persistentie gedrag configureren:
FirebaseFirestore.instance.settings = Settings(
persistenceEnabled: true,
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
);De default cache size is 40MB. Voor apps met veel data is CACHE_SIZE_UNLIMITED aan te raden, maar dit kan storage problemen veroorzaken op devices met weinig ruimte.
Repository Pattern voor Testbare Code
Direct gebruik van Firestore in UI code maakt unit testing complex. Het Repository pattern scheidt data access logica van business logic.
abstract class TaskRepository {
Future<String> create(String userId, String title);
Stream<List<Task>> watchAll(String userId);
Future<void> update(String id, Map<String, dynamic> fields);
Future<void> delete(String id);
}
// firebase_task_repository.dart
class FirebaseTaskRepository implements TaskRepository {
final _db = FirebaseFirestore.instance;
Future<String> create(String userId, String title) async {
final doc = await _db.collection('tasks').add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
Stream<List<Task>> watchAll(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((s) => s.docs.map(Task.fromFirestore).toList());
}
// ... update and delete implementations
}Dit patroon maakt het mogelijk om een MockTaskRepository te creëren voor unit tests. De business logic blijft ongewijzigd, alleen de repository implementatie wordt vervangen. State management-oplossingen zoals Riverpod of BLoC gebruiken de repository-interface zonder iets van Firestore te weten.
Packages zoals get_it of riverpod maken het eenvoudig om repository instances te injecteren. Dit verbetert testability en maakt het wisselen tussen implementaties (bijv. Firebase vs local database) triviaal.
Upgraden naar FlutterFire 5: wat er breekt
De major release van oktober 2026 (BoM 5.0.0, firebase_auth 7.0.0, cloud_firestore 7.0.0, firebase_core 5.0.0) verandert vooral de buildvereisten, minder de Dart-API's. Op deze punten faalt een build of een review:
- Android-
minSdk24: de plugins bouwen op de Firebase Android BoM 35. Een project dat nog opminSdk21 of 23 staat, compileert niet meer. - Apple SDK 13: de Firebase Apple SDK gaat naar 13.0.0 met Swift Package Manager (12.19.0 met CocoaPods), en Swift packages vereisen macOS 11.
- App Check: de
activate-parameters heten nuproviderWeb,providerAndroidenproviderApple. - Deprecations:
setIndexConfigurationFromJSONis deprecated incloud_firestore7.0.0, enfirebase_ml_model_downloaderwordt niet meer gepubliceerd. - Al verwijderd in de 6.x-reeks:
fetchSignInMethodsForEmail()enUser.updateEmail(). Code die vóór het inloggen controleert welke provider een e-mailadres gebruikt, moet opnieuw worden ontworpen, omdat de bescherming tegen e-mailenumeratie die informatie verbergt.
De volledige lijst per package staat in de FlutterFire release notes en de changelog van cloud_firestore.
Firebase-interviewvragen voor Flutter-developers
Interviews toetsen zowel conceptueel begrip als de praktische implementatie van Firebase-diensten. De volgende vragen komen in 2026 regelmatig terug in interviews voor Flutter-developers. De bredere gids met Flutter-interviewvragen behandelt de frameworkkant.
Wat is het verschil tussen authStateChanges(), idTokenChanges() en userChanges()?
authStateChanges() vuurt alleen bij in- en uitloggen. idTokenChanges() vuurt daarnaast wanneer het ID-token wordt vernieuwd (ongeveer elk uur). userChanges() vangt dat allemaal op, plus profielwijzigingen zoals updateDisplayName(). Voor de meeste navigation guards volstaat authStateChanges().
Wat is het verschil tussen set() en update() in Firestore?
De set() methode overschrijft het volledige document. Als het document niet bestaat, wordt het aangemaakt. De update() methode wijzigt alleen opgegeven velden en faalt als het document niet bestaat. Voor partiële updates is update() de juiste keuze.
Hoe werkt de offline synchronisatie van Firestore?
Firestore gebruikt een lokale SQLite database om alle gelezen documenten te cachen. Writes worden opgeslagen in een write-ahead log en automatisch gesynchroniseerd bij netwerkverbinding. De snapshots() stream emits eerst cached data, gevolgd door server updates.
Waarom is FieldValue.serverTimestamp() beter dan DateTime.now()?
Client timestamps zijn onbetrouwbaar door tijdzone verschillen en gemanipuleerde device clocks. Server timestamps garanderen consistente ordering en worden pas ingevuld na de write commit.
Hoe voorkom je N+1 queries bij nested collections?
Firestore ondersteunt geen joins. Voor relational data gebruiken developers denormalization (data dupliceren) of batched reads met whereIn() queries. Collection Group Queries kunnen queries uitvoeren over alle subcollections met dezelfde naam.
Hoe modelleer je Firestore-data voor een chatapplicatie?
Een collection chats waarin elk document de metadata bevat (deelnemers, timestamp van het laatste bericht), met onder elk chatdocument een subcollection messages. Met deze structuur haal je de chatlijst van een gebruiker efficiënt op en pagineer je de berichten binnen elk gesprek. Het laatste bericht wordt gedenormaliseerd in het bovenliggende document, zodat de lijstweergave de subcollection niet hoeft te lezen.
Wat zijn de limieten van Firestore composite indexes?
Elke query die meerdere where() clauses combineert met orderBy() vereist een composite index. Firebase genereert automatisch single-field indexes, maar composite indexes moeten handmatig worden aangemaakt via de Console of firestore.indexes.json.
Wanneer gebruik je een transactie in plaats van een batched write?
Een transactie is nodig wanneer de write afhangt van data die in dezelfde operatie wordt gelezen, bijvoorbeeld de voorraad alleen verlagen als die boven nul ligt. De SDK voert de callback opnieuw uit als een gelezen document vóór de commit verandert, dus de callback mag geen side effects hebben. Een batched write voert meerdere writes atomair uit zonder enige read, bijvoorbeeld een document aanmaken en elders een teller ophogen. Offline gedragen ze zich verschillend: een batch komt in de wachtrij, een transactie faalt zonder verbinding.
final db = FirebaseFirestore.instance;
// Transaction: read then write, retried on contention
await db.runTransaction((tx) async {
final ref = db.collection('products').doc(id);
final snap = await tx.get(ref);
final stock = snap.get('stock') as int;
if (stock <= 0) throw Exception('Out of stock');
tx.update(ref, {'stock': stock - 1});
});
// Batched write: atomic writes, no reads
final batch = db.batch();
batch.set(db.collection('orders').doc(), {'productId': id});
batch.update(db.collection('stats').doc('orders'), {
'count': FieldValue.increment(1),
});
await batch.commit();Hoe implementeer je een adminrol met Firebase?
Met custom claims die vanuit een vertrouwde omgeving via de Admin SDK worden gezet, nooit vanuit de Flutter-client. De claim reist mee in het ID-token, dus rules lezen hem als request.auth.token.admin == true zonder extra document-lookup. De documentatie over custom claims beperkt de payload tot 1000 bytes, en de client ziet een nieuwe claim pas na een tokenvernieuwing, die currentUser.getIdToken(true) afdwingt.
Wat is het verschil tussen security rules en App Check?
Security rules bepalen of een bepaalde gebruiker een bepaald document mag lezen of schrijven. App Check bevestigt dat het verzoek van de echte app op een echt toestel komt, wat scripts blokkeert die de publieke API-key hergebruiken. Ze beantwoorden verschillende vragen, dus een productie-app heeft ze allebei nodig. Sinds FlutterFire 5 wordt App Check geactiveerd met providerAndroid, providerApple en providerWeb.
Waarom kan een Firestore-scherm duur worden, en hoe werkt paginering?
Firestore factureert per gelezen, geschreven en verwijderd document. Een listener op een onbegrensde collection leest bij de eerste load elk overeenkomend document, daarna één read per gewijzigd document. Paginering gebruikt query cursors in plaats van offsets: limit(20) voor de eerste pagina, daarna startAfterDocument(lastDoc) voor de volgende, zodat elke pagina alleen de documenten kost die ze teruggeeft.
Firestore of Realtime Database: welke en waarom?
Firestore slaat documenten op in collections, ondersteunt samengestelde queries met indexes en factureert per operatie. De Realtime Database slaat één JSON-boom op, biedt ondiepe queries op één child key en factureert vooral op bandbreedte en opslag, wat past bij kleine, zeer frequente updates zoals presence-indicatoren. De meeste nieuwe Flutter-apps starten op Firestore en voegen de Realtime Database alleen toe voor presence.
Voor verdere voorbereiding op Flutter-interviews behandelen speciale oefenmodules deze onderwerpen met interactieve quizzen en challenges op tijd.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Bronnen
- Firebase release notes voor Flutter: inhoud van BoM 5.0.0 en 5.1.0, minSdk 24, hernoemde App Check-parameters
- Changelog van cloud_firestore: Pipelines in 6.3.0,
FieldValue.minimum/maximumenfindNearest-afstand in 7.1.0 - Changelog van firebase_auth:
validatePasswordin 6.0.0, TOTP op macOS in 6.1.0, verwijderdefetchSignInMethodsForEmail - Migratiegids van google_sign_in: singleton,
initialize,authenticate, aparte autorisatie in 7.0 - Firebase custom claims: limiet van 1000 bytes en tokenvernieuwing
Flutter en Firebase in het interview: de kernpunten
- FlutterFire BoM 5.1.0 levert
firebase_auth7.0.1 encloud_firestore7.1.0 en vereist Android-minSdk24 google_sign_in7 vervangtGoogleSignIn().signIn()doorGoogleSignIn.instance.initialize()gevolgd doorauthenticate(), en Firebase heeft alleen hetidTokennodigauthStateChanges()levert een reactieve stream die de loginstatus in de hele app beheert zonder handmatige checks- Realtime synchronisatie via
snapshots()maakt polling overbodig en sluit direct aan opStreamBuildervoor automatische UI-updates - Security rules zijn verplicht in productie: controleer
request.auth.uidaltijd tegen de eigenaarsvelden van het document en gebruik custom claims voor rollen - Transacties lezen en schrijven daarna met retries, batched writes schrijven alleen; paginering gebruikt cursors omdat elk gelezen document gefactureerd wordt
- Offline persistence werkt op mobiel zonder extra code;
hasPendingWritestoont gebruikers de synchronisatiestatus - Het Repository pattern ontkoppelt Firebase van de business logic, wat testen en latere migraties eenvoudiger maakt
Zie jij de bug in Flutter?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 9 november 2026
Tags
Delen
Gerelateerde artikelen

Flutter State Management: Riverpod vs BLoC - Volledige Vergelijkingsgids
Diepgaande vergelijking tussen Riverpod 3.x en BLoC 9.x voor state management in Flutter. Architectuur, automatische retry, testbaarheid en use cases om de beste oplossing te kiezen.

Top 20 Flutter Sollicitatievragen voor Mobiele Ontwikkelaars
Bereid je voor op Flutter-sollicitatiegesprekken met de 20 meest gestelde vragen. Widgets, state management, Dart, architectuur en best practices uitgelegd met codevoorbeelden.

Flutter: Een eerste cross-platform applicatie bouwen
Volledige gids voor het bouwen van een mobiele cross-platform applicatie met Flutter en Dart. Widgets, statusbeheer, navigatie en best practices voor beginners.