Spring til indhold
App-udvikling

Hvorfor jeg bruger Firebase og Firestore

Der findes to typer backend-projekter.

Den ene type starter med en database, et API, auth, hosting, miljøvariabler, adgangskontrol, logning, deploy-pipeline og en lille bøn til skyen om, at alt opfører sig anstændigt.

Den anden type starter med, at brugeren faktisk kan gøre noget i appen.

Jeg har efterhånden brugt en del tid på at vælge den anden type.

Jeg hedder Halfdan Harring, og jeg bygger apps fra et skrivebord i Aarhus, ofte alene, fra første skitse til noget folk kan bruge på web, iOS og Android. Det lyder romantisk, indtil man husker, at “alene” også betyder, at ingen andre lige fikser backend’en søndag aften.

Derfor bruger jeg Firebase. Og især Firestore.

Ikke fordi det er perfekt. Det er det ikke. Men fordi det passer næsten urimeligt godt til den måde, jeg bygger produkter på: hurtigt, konkret, realtime, på tværs af platforme, og uden at skulle drive en lille server-farm forklædt som en hobby.

Hvis du vil vide mere om, hvordan jeg bygger produkter generelt, har jeg skrevet lidt på om-siden.

Hvad er Firebase egentlig?

Firebase er Googles backend-platform til apps. Det er ikke én ting. Det er en samling af hosted backend-services, som du kan bruge uden selv at sætte servere op, patche dem, skalere dem, overvåge dem og langsomt udvikle den der stirren ud ad vinduet, man får af infrastrukturarbejde.

I praksis betyder det, at Firebase kan give dig mange af de ting, en moderne app typisk har brug for:

Authentication til login. Firestore til databasen. Cloud Functions til backend-logik. Cloud Storage til filer. Hosting til webappen. Cloud Messaging til push-beskeder. Og en række værktøjer til analytics, crash reporting og drift rundt om det hele. Firebase beskriver selv platformen som services til at bygge og køre apps hurtigere, sikrere og mere skalerbart, og listen af produkter inkluderer blandt andet Authentication, Cloud Functions, Cloud Storage og Firestore.

Det er backend-as-a-service. Et lidt kedeligt udtryk, men et ret præcist et.

I stedet for at bygge hele backend-laget selv, bruger du Firebase SDK’et direkte fra din app. I mit tilfælde typisk fra en React/Capacitor-app, hvor den samme kodebase ender som web, iOS og Android. Det er den slags teknisk genbrug, der får en soloudvikler til at ligne en lille afdeling. Indtil man åbner GitHub Issues.

Hvad er Firestore?

Firestore er databasen i Firebase, og det er den del, jeg bruger mest.

Mere præcist er Firestore en realtime, NoSQL, dokumentbaseret database. Det betyder, at du ikke tænker i SQL-tabeller og rækker på samme måde som i en klassisk relationel database. Du tænker i collections og documents.

En collection kan for eksempel hedde matches.

Inde i den ligger documents. Ét document per kamp, quizrunde, liga, brugerprofil eller hvad din app nu har brug for. Et document er grundlæggende et objekt med felter: tekst, tal, datoer, arrays, maps og referencer. Det minder på overfladen meget om JSON, hvilket passer ret naturligt til JavaScript- og TypeScript-apps.

Så i stedet for noget som:

SELECT * FROM matches WHERE league_id = ...

tænker du mere:

“Hent dokumenterne i matches, hvor leagueId er den her værdi, sortér dem sådan, og lyt efter ændringer.”

Det lyder som en lille forskel. Det er det ikke.

Firestore tvinger dig til at modellere data efter de spørgsmål, din app faktisk stiller. Ikke efter en pæn, akademisk datamodel, som ville gøre en databasebog fra 2007 stolt. Firestore beskrives i dokumentationen som en fleksibel, skalerbar NoSQL cloud-database til mobile, web- og server-apps, med data sync på tværs af klienter via realtime listeners.

Det er enormt effektivt, når man bygger app-UI’er, der skal reagere live. Men det kræver også, at man tænker sig om. Mere om den irriterende del senere.

Realtime er ikke en feature. Det er en arkitekturændring.

Den største grund til, at jeg bruger Firestore, er realtime.

I mange traditionelle setups spørger appen backend’en: “Har noget ændret sig?” Backend’en svarer. Appen opdaterer måske UI’et. Gentag. Rør rundt. Tilsæt polling, websockets eller en beskedkø, hvis du gerne vil gøre din tirsdag mere karakteropbyggende.

I Firestore kan du sætte en listener på et document eller en query. Når data ændrer sig, får klienten besked, og UI’et opdaterer. Firebase-dokumentationen viser netop det mønster med onSnapshot(), hvor en listener først får det aktuelle indhold og derefter nye snapshots, når dokumentet ændrer sig.

Det er svært at overvurdere, hvor meget det ændrer måden man bygger på.

I Quiz Fight, som er live 1v1 trivia med mere end 500.000 AI-genererede spørgsmål, er realtime ikke pynt. Det er selve oplevelsen. To spillere sidder i hver sin ende og skal se runder, svar, status og progression føles levende. Hvis den ene spiller svarer, skal den anden ikke trykke refresh som en revisor i et kommunalt sagsbehandlingssystem.

Det samme gælder HeadToHead, hvor brugere laver fodboldforudsigelser i private ligaer. Point, picks, runder og stillinger bliver meget hurtigt noget rod, hvis data ikke føles opdateret. Private ligaer er sociale. Og sociale apps bliver døde, hvis de føles døde.

Firestore gør ikke designet for dig. Det gør heller ikke produktet godt. Det ville være for nemt, og derfor naturligvis ulovligt. Men det giver et fundament, hvor realtime-adfærd ikke kræver, at jeg bygger et helt separat system ved siden af databasen.

Offline support er den slags ting, man først savner, når den mangler

Firestore har også offline support. Det betyder, at appen kan cache data lokalt, så brugeren stadig kan læse, skrive, lytte og query’e cached data, selv når forbindelsen er dårlig eller væk. Når forbindelsen kommer tilbage, synkroniseres ændringerne.

Det er ikke altid noget, man sælger en app på.

“Nu med lokal cache og pænere håndtering af netværkslatens” er sjældent en overskrift, der får folk til at smide confetti ud over kontoret. Men i praksis betyder det meget. Især på mobil.

Brugere tænker ikke: “Mit netværk skiftede lige mellem Wi-Fi og 5G, så det er fair nok, at appen opfører sig som en printer fra 1998.”

De tænker: “Appen er dårlig.”

Firestore hjælper med at gøre den slags overgange mindre dramatiske. Ikke magiske. Bare mindre dumme. Det er rigeligt i mange tilfælde.

Security Rules: derfor behøver jeg ofte ikke et klassisk API

En af de mest undervurderede dele af Firebase er Security Rules.

Normalt ville man bygge et API mellem klienten og databasen. Klienten kalder API’et. API’et tjekker, hvem brugeren er. API’et afgør, hvad brugeren må læse og skrive. API’et taler med databasen.

Det er en glimrende model. Den er også endnu et lag, man skal bygge, teste, deploye og vedligeholde.

Med Firestore kan klienten tale direkte med databasen via Firebase SDK’et, mens Security Rules håndhæves server-side. Reglerne bestemmer, hvem der må læse og skrive hvilke dokumenter, og under hvilke betingelser. Firebase beskriver Security Rules som et værktøj til at sikre data i blandt andet Cloud Firestore og Cloud Storage.

Det betyder ikke, at man bare fyrer databasen direkte ud på internettet og håber på det bedste. Det er ikke en sikkerhedsmodel. Det er en invitation.

Men det betyder, at meget adgangskontrol kan ligge tæt på databasen. For eksempel:

  • En bruger må læse sin egen profil.
  • Et medlem af en privat liga må læse ligaens kampe.
  • Kun ejeren af en bestemt ressource må opdatere den.
  • En quizspiller må kun skrive sit eget svar i en aktiv runde.

Den slags regler passer godt til apps, hvor dataadgang ofte følger brugerens identitet og relation til et document. Firebase Authentication spiller tæt sammen med det, fordi Auth giver login og brugeridentitet, som reglerne kan bruge. Firebase Authentication leverer backend-services og SDK’er til at autentificere brugere, blandt andet med password, telefonnummer og federated providers.

Der er stadig masser af situationer, hvor jeg bruger Cloud Functions. Betalinger, hemmelige API-nøgler, AI-kald, server-side validering, batchjobs og alt, der ikke bør ligge i klienten. Cloud Functions for Firebase er netop lavet til at køre backend-kode i et managed miljø uden at administrere egne servere.

Men pointen er, at jeg ikke skal bygge et fuldt API for hver eneste CRUD-operation. Det sparer tid. Og tid er den mest ærlige valuta, når man bygger alene.

Firebase erstatter ikke omtanke. Det erstatter meget VVS-arbejde.

Det, Firebase gør for mig, er ikke at fjerne backend. Det fjerner en stor del af den backend, der ellers ikke er særlig tæt på produktet.

Jeg vil gerne bruge tid på spilflowet i Quiz Fight. På hvordan en livekamp føles. På hvordan HeadToHead gør private fodboldligaer nemme nok til, at folk faktisk gider bruge dem. På hvordan TaskMondo kan samle arbejde uden at blive et glorificeret skuffemøbel. På hvordan LostLead kan hjælpe med AI lead recovery uden at føles som endnu en “growth platform”, der har drukket seks espressoer og glemt menneskelig kontakt.

Jeg vil ikke bruge uforholdsmæssigt meget tid på at provisionere servere, opsætte auth, skrive boilerplate API-lag, lave min egen realtime-infrastruktur og bagefter sidde med drift, skalering og sikkerhedsopdateringer.

Selvfølgelig skal man stadig forstå, hvad man laver. Firebase er ikke en autopilot. Det er mere som en ret dygtig medpilot, der tager mange af de kedelige kontroller, men stadig forventer, at du ikke flyver direkte ind i en bakke.

Den bredere stack — React, Capacitor, Vite og resten — har jeg skrevet om i Min tech stack med React og Capacitor. Firebase og Firestore fortjener næsten deres egen lille psykologiske udredning. Den er den her.

Hvor Firebase især passer til min måde at arbejde på

Jeg bygger typisk produkter, hvor hastighed betyder noget.

Ikke hastighed på den der LinkedIn-måde, hvor “move fast” mest betyder “vi har ikke skrevet tests”. Mere praktisk hastighed. Fra idé til noget, der kan prøves. Fra prototype til app. Fra app til brugerfeedback. Fra brugerfeedback til næste version.

Firebase passer godt til den rytme.

Jeg kan starte med Authentication, Firestore og Security Rules. Så har jeg login, database og adgangskontrol. Jeg kan tilføje Cloud Functions, når der er brug for server-side logik. Jeg kan bruge Cloud Storage til filer. Firebase Hosting kan tage webdelen. Cloud Messaging kan håndtere push, når appen skal prikke brugeren på skulderen på den mindst irriterende måde, man nu kan prikke nogen på skulderen digitalt. Firebase Cloud Messaging er dokumenteret som en cross-platform messaging-løsning til beskeder og notifikationer, og Hosting er lavet til hurtig og sikker hosting af webapps via global CDN.

Det hele hænger sammen.

Det er især værdifuldt, når én React-codebase skal køre på web, iOS og Android. Firebase SDK’et giver mig et fælles backend-lag, som ikke kræver tre forskellige måder at tænke data på. Det lyder banalt. Det er det ikke, når man også gerne vil spise aftensmad og lejlighedsvis være et nogenlunde tilstedeværende menneske. Jeg er for nylig blevet far, så “lejlighedsvis” er allerede et ambitiøst ord.

Trade-offs: her bliver det mindre brochure-agtigt

Firestore er ikke det rigtige valg til alt.

Den første trade-off er datamodellering. NoSQL betyder, at du skal modellere efter dine queries. Du får ikke SQL-joins, som du kender dem fra relationelle databaser. Hvis din app er dybt relationel, med komplekse rapporter, fleksible joins, tunge aggregater og mange uforudsigelige query-mønstre, kan Firestore begynde at føles som at spise suppe med en gaffel. Det kan lade sig gøre længe nok til, at man bliver stædig. Det gør det ikke klogt.

I Firestore ender man ofte med at denormalisere data. Man gemmer måske den samme lille bid data flere steder, fordi det gør læsninger hurtigere og enklere. Det er fint, hvis man gør det bevidst. Det er mindre fint, hvis man opdager det tre måneder senere ved at stirre på fem næsten ens felter med forskellige sandheder.

Den anden trade-off er pris. Firestore har en pay-per-operation-model, hvor læsninger, skrivninger, deletes, storage og netværk indgår i afregningen. Firebase viser blandt andet gratis kvoter for document reads, writes og deletes og derefter usage-baseret betaling.

Det kan være meget billigt. Det kan også blive overraskende dyrt, hvis man designer dumt.

Realtime listeners er fantastiske, men de er ikke gratis tryllestøv. Hvis du lytter på for brede queries, opdaterer for ofte, eller renderer skærme, der konstant genhenter data, kan regningen og performance begynde at kigge på dig med hævede øjenbryn.

Den tredje trade-off er lock-in.

Firebase er Google. Firestore er ikke bare en Postgres-database, du kan flytte i weekenden med en kop kaffe og lidt moralsk fleksibilitet. Du bygger op mod deres SDK’er, deres regler, deres datamodel og deres økosystem. Det skal man være ærlig om.

For mig er det trade-off ofte det værd.

Jeg optimerer ikke efter teoretisk portabilitet fem år ude i fremtiden. Jeg optimerer efter at få et rigtigt produkt ud til rigtige brugere uden at drukne i backend-arbejde på vejen. Det kan man være uenig i. Det er helt tilladt. Internettet ville jo også kede sig uden.

Hvornår jeg ikke ville vælge Firestore

Jeg ville være forsigtig med Firestore, hvis produktet primært er et rapporteringsværktøj med komplekse relationer og mange ad hoc-queries.

Jeg ville også tænke mig om, hvis datamodellen kræver tunge transaktioner på tværs af mange entiteter hele tiden, eller hvis teamet allerede har en stærk SQL-infrastruktur og ikke har brug for realtime, offline og klient-SDK-modellen.

Og jeg ville ikke vælge Firebase bare for at vælge Firebase.

Det er fristende at gøre sin stack til en identitet. React-menneske. Postgres-menneske. Firebase-menneske. Vim-menneske. Den sidste gruppe bør vi naturligvis møde med omsorg.

Jeg prøver at være mere praktisk end religiøs. Firebase og Firestore er værktøjer. Gode værktøjer. Men stadig værktøjer.

Hvorfor jeg bliver ved med at bruge det

Jeg bruger Firebase og Firestore, fordi det lader mig bygge apps, der føles levende, uden at jeg først skal bygge hele maskinrummet selv.

I Quiz Fight betyder det live 1v1 trivia, hvor data bevæger sig hurtigt nok til, at spillet føles som et spil. I HeadToHead betyder det private fodboldligaer, hvor stillinger og picks kan følge med. I mine andre produkter betyder det, at jeg kan komme fra idé til brugbar version uden at miste tre uger til backend-infrastruktur, som brugeren aldrig kommer til at se.

Det er ikke en universel anbefaling. Det er min anbefaling til den type udvikler, der gerne vil shippe rigtige produkter hurtigt, især alene eller i et lille team, og som bygger apps hvor realtime, offline, auth og cross-platform betyder noget.

Man skal lære Firestores måde at tænke data på. Man skal holde øje med reads. Man skal skrive ordentlige Security Rules. Man skal acceptere, at Google sidder ret solidt med nøglerne til huset.

Men til gengæld får man en backend, der kan bære rigtige produkter, uden at man selv skal stå nede i kælderen med en lommelygte hver gang nogen trykker på en knap.

Det er en meget lavpraktisk form for luksus. Og den slags skal man ikke kimse ad. Især ikke når man også gerne vil nå et afsnit af The Office, før barnet vågner.