Offline‑First‑SQL‑Synchronisierung, die Ihr Backend nicht zum Schmelzen bringt: Ein CTO‑Playbook

Von Diogo Hudson Dias
Field technician using a tablet at a São Paulo construction site while a nearby laptop displays database sync metrics.

Der Offline‑Modus Ihrer App ist wahrscheinlich nur ein Lade‑Spinner und ein Stoßgebet. Dann fährt ein Außendienstteam in einen Tunnel, fünf Auslieferungen stauen sich, und Ihr Backend erlebt einen Write‑Storm, sobald sie wieder online sind. Show HN hat gerade mit Syncular aufgeleuchtet—Offline‑First‑SQL‑Sync mit TypeScript‑ und Rust‑Kernen—und erinnert alle daran, dass Local‑first kein Spielzeug mehr ist. Wenn Sie mobile, Edge‑ oder regulierte Workflows bedienen, müssen Sie Synchronisierung als Produkt behandeln, nicht als Retry‑Policy.

Gute Nachricht: Sie können Offline‑First mit purem SQL und einer soliden Sync‑Schicht liefern—ohne Ihren Stack neu zu schreiben oder eine Sonderdatenbank einzuführen. Schlechte Nachricht: Sie müssen ein paar nicht verhandelbare Designentscheidungen gleich zu Beginn treffen—Oplog‑Format, Konflikt‑Semantik, Schema‑Migrationsstrategie, selektive Synchronisierung, Observability und Gerätesicherheit. Wenn Sie diese richtig setzen, bekommen Sie vorhersehende Konvergenz, einen begrenzten Blast‑Radius und ein Backend, das nicht einknickt, wenn um 17:01 Uhr 10.000 Telefone wieder verbinden.

Wann Offline‑First wirklich auszahlt

Offline‑First ist keine Funktion; es ist eine Architekturausrichtung. Es zahlt sich aus, wenn:

  • Geräte in und außerhalb der Abdeckung arbeiten: Kuriere, Inspektoren, Field Service, Kassenplätze im Einzelhandel (POS), Visiten im Gesundheitswesen und Baustellen. Rechnen Sie mit Unterbrechungen im Bereich von zig Minuten bis Stunden—nicht Sekunden.
  • Latenz wichtiger ist als strikte Serialisierbarkeit: Beweise erfassen, Artikel scannen, Notizen protokollieren oder Zahlungen annehmen, die später beglichen werden können.
  • Datenschutz‑ oder Regulierungsvorgaben Berechnung an den Rand schieben: On‑Device‑PII‑Redaktion, klinische Notizen oder Client‑seitige Inferenz.

Brazil und die weitere LATAM‑Region sind Musterbeispiele für Offline‑First‑Märkte: dichte Metropolen mit Funklöchern, Langstreckenreisen und viele Prepaid‑Datentarife. Wenn Sie für diese Realitäten bauen (oder für US‑Außeneinsätze, die genauso aussehen), brauchen Sie ein Sync‑Modell, das langweilig zuverlässig ist.

Das Minimal Viable Sync (MVS): SQL + Oplogs + deterministische Merges

Sie brauchen keine Magie. Sie brauchen ein begrenztes, testbares Protokoll, das auf Ihren Clients läuft und in Ihre Source of Truth (oft Postgres) zusammenführt:

1) Primärschlüssel sind unveränderlich und global eindeutig

  • Verwenden Sie UUIDv7 (zeitstempel‑geordnet) oder ULIDs für Zeilen, die auf dem Gerät erstellt werden. Primärschlüssel niemals umwidmen.
  • Fremdschlüssel stabil halten; vermeiden Sie zusammengesetzte Schlüssel für synchronkritische Tabellen.

2) Änderungen werden als Append‑only‑Oplog ausgedrückt

  • Jeder Client hängt Operationen (insert/update/delete) an eine lokale Oplog‑Tabelle an mit: op_id (UUID), table, row_id, site_id (Gerät), counter (monoton pro Gerät), timestamp, op_type, payload (Spaltendeltas) und optionalen Domain‑Metadaten.
  • Deletes sind Tombstones mit einem expliziten deleted_at‑Feld. Hard‑Deletes nur für Archivierungsaufgaben.
  • Sync‑Batches streamen Oplog‑Einträge an einen Server‑Endpunkt, der validiert, zusammenführt und serverseitig akzeptierte Ops plus verpasste Remote‑Ops zum Pull zurückgibt.

3) Versionsvektoren für kausale Ordnung

  • Pflegen Sie einen per‑Gerät‑Zähler und einen kompakten Versionsvektor auf dem Server (und optional pro Zeile), um zu berechnen, was jeder Seite fehlt.
  • So vermeiden Sie quadratisches Diffing—und warum naive „Vergleiche den neuesten Zeitstempel“-Lösungen unter Clock‑Skew auseinanderfallen.

4) Deterministische Konflikt‑Semantik

  • Standardmäßig Last‑Writer‑Wins (LWW) auf Spaltenebene für nicht kritische Daten. Einfach und vorhersehbar.
  • Für Geld, Inventar und idempotente Zähler CRDTs (z. B. PN‑Counters) oder domänenspezifische Merges verwenden. Wenden Sie kein „LWW“ auf Währungen an.
  • Für echte Konflikte, die Menschen lösen sollen, Multi‑Value‑Register einsetzen; alle Kandidaten speichern und eine Aufgabe auslösen.

Wenn das nach dem klingt, was Syncular, ElectricSQL, cr-sqlite, Realm, Couchbase Lite und Replicache‑Varianten tun—so ist es. Die Muster konvergieren, weil das Problem alt ist. Der Unterschied liegt darin, ob Sie SQL, CRDT‑Reichtum oder Developer‑Ergonomie priorisieren.

Konfliktstrategie: Bei 80 % langweilig, bei 20 % präzise

Die meisten Schemata haben drei Kategorien von Tabellen. Behandeln Sie sie unterschiedlich.

Kategorie A: Ereignislogs und Telemetrie (LWW oder Append‑only)

  • Beispiele: Audit‑Trails, Lesebestätigungen, Nutzungsprotokolle. Vergangene Zeilen werden selten aktualisiert; Sie hängen an oder LWW auf triviale Felder.
  • Storage‑Tipp: Payloads komprimieren und bündeln, um Netzwerklärm zu reduzieren.

Kategorie B: Dokumente und Profile (feldweises LWW + menschliche Auflösung)

  • Beispiele: Kundenprofile, Formulare, Notizen.
  • Vorgehen: Feldweises LWW für die meisten Spalten; Multi‑Value‑Register für Felder, bei denen Divergenz zählt (z. B. amtlicher Name). Einen deterministischen Konfliktschlüssel erzeugen, damit Menschen nur einmal auflösen.

Kategorie C: Zähler und Inventar (CRDTs oder domänennahe Merges)

  • Beispiele: Bestände, Zählerstände, finanzielle Anpassungen.
  • Vorgehen: PN‑Counters für Inkremente/Dekremente; Observed‑Remove‑Sets (OR‑Set) für Mitgliedschaften; für Geld unveränderliche Buchungseinträge persistieren und Salden berechnen—keine Salden überschreiben.

Daumenregel: Zielen Sie darauf ab, dass unter 0,5 % der Sync‑Batches im Normalbetrieb menschlich sichtbare Konflikte erzeugen. Wenn es mehr sind, lassen Sie Menschen Ihr Konsistenzmodell debuggen.

Schema‑Migrationen unter Sync, ohne eine Woche frei zu nehmen

Schemaänderungen sind der Ort, an dem Offline‑First‑Projekte sterben. Setzen Sie jetzt Leitplanken:

  • Zuerst additiv: neue Spalten/Tabellen hinzufügen; nicht in Place droppen oder umbenennen. Backfills und Dual‑Write‑Transforms während eines Übergangsfensters nutzen.
  • Versions‑gesteuerte Synchronisierung: Jeder Client deklariert eine Schema‑Version; der Server verweigert Sync jenseits von N‑1. Erzwingen Sie einen Upgrade‑Pfad, bevor Sie eine destruktive Migration ausliefern.
  • Transformation an den Rändern: Wenn aus dem „status“-Enum „state + substate“ wird, wendet Ihr Sync‑Ingress eine deterministische Transformation für alte Clients an und schreibt während des Cutovers beide Formen.
  • Schatten‑Migrationen: Migrationen in zwei Phasen deployen—neue Strukturen + Transformer anlegen, dann Reads umschalten, schließlich nach einem vollständigen Geräte‑Upgrade‑Zyklus aufräumen.

Praktisches Ziel: eine Breaking‑Migration pro Quartal mit einem Upgrade‑Fenster von 14–28 Tagen unterstützen. Alles Schnellere lässt Geräte stranden.

Selektive Synchronisierung und Privacy by Default

Die ganze Datenbank auf jedes Gerät zu pushen, bringt Sie in die Nachrichten. Selektivität ist Ihr Freund—für Performance, Kosten und Compliance.

  • Row‑Level‑Filter: nur Teams eines Nutzers, zugewiesene Routen oder nahegelegenes Inventar synchronisieren. Filterprädikate beim Login kodieren und mit Auth‑Tokens rotieren.
  • Spaltenweises Redacting: Keine SSNs, Karten‑PANs oder Secrets auf Geräte synchronisieren. Für sensible, aber notwendige Felder Feld‑level‑Verschlüsselung erwägen.
  • Attachment‑Policy: Binärdaten sind Ihr Untergang. Größe der initialen Synchronisierung begrenzen (z. B. 100–200 MB), große Dateien in Chunks aufteilen und Previews per Lazy‑Load mit expliziter Nutzeraktion laden.
  • Geräte‑Lifecycle: Gerätespezifische Credentials, Attestation wo verfügbar, Remote‑Wipe und ein Off‑Ramp, wenn ein Gerät Check‑ins verpasst.

Wenn Sie End‑to‑End‑Verschlüsselung (E2EE) für bestimmte Spalten brauchen, akzeptieren Sie, dass serverseitige Suche und serverinitiierte Transformationen auf diesen Feldern ausfallen. Selektive Synchronisierung auf verschlüsselten Blobs ist mit serverseitig gehaltenen Filter‑Keys weiterhin möglich, aber Sie werden nicht indexieren, was Sie nicht sehen.

Kapazitätsplanung: Lassen Sie Reconnect‑Spikes Ihre DB nicht abfackeln

Rechnen Sie vor dem Launch:

  • Operationen pro Gerät und Tag: Starten Sie mit 300–1.000 Writes und dem 2–5‑fachen an Reads für typische Field‑Apps.
  • Oplog‑Eintragsgröße: 150–300 Bytes für Metadaten + Deltas, wenn Sie ausführliches JSON vermeiden; 0,5–1,0 KB, wenn Sie ganze Zeilen als JSON serialisieren. Wählen Sie mit Bedacht.
  • Überschlagsrechnung: 10.000 Geräte × 1.000 Ops/Tag × 250 Bytes ≈ 2,5 GB/Tag an Ingress in Ihre Sync‑Schicht. Wenn 30 % in einem 10‑Minuten‑Fenster reconnecten, müssen Sie ~75 MB Ops pro Minute absorbieren—plus Read‑amplifizierte Pulls.
  • Batching: Batches nach Größe (z. B. 256–512 KB) und Zeit (z. B. 250 ms) deckeln, um Reconnect‑Stürme zu glätten.

Ihre Source of Truth ist Postgres? Schalten Sie einen Message‑Broker und einen dedizierten Merge‑Service davor. Vermeiden Sie, dass Tausende Geräte Ihren DB‑Connection‑Pool direkt zuschlagen. Erwägen Sie Write‑Ahead‑Queues pro Mandant, dann Merges in kontrollierten Workern mit Rate‑Limits anwenden.

Observability und SLOs für Sync (damit Sie schlafen können)

Wenn Sie es nicht sehen, ist es nicht konvergiert. Behandeln Sie Sync wie eine Payment‑Pipeline mit klaren SLOs:

Metriken, die Sie ab Tag eins instrumentieren sollten

  • sync_batch_ingest_latency_ms (P50/P95/P99)
  • sync_batch_apply_latency_ms (server-side merge)
  • device_backlog_ops (gauge) and backlog_age_seconds
  • merge_conflict_rate (per table/column)
  • time_to_convergence_seconds after reconnection (P50/P95)
  • bytes_synced_per_device_per_day and initial_full_sync_bytes

Empfohlene SLOs

  • P95‑Zeit bis zur Konvergenz unter 120 Sekunden, nachdem ein Gerät die Konnektivität wiedererlangt.
  • Merge‑Konfliktrate unter 0,5 % der Batches im Gleichgewicht.
  • Initiale Gerätesynchronisierung innerhalb von 5 Minuten über medianes 4G.
  • Kein Datenverlust: nach op_id deduplizieren; jede Operation ist idempotent anwendbar.

Testen—aber richtig

  • Jepsen‑ähnliches Chaos: Zeitskew ±15 Minuten, doppelte Batches, Out‑of‑Order‑Zustellung, simulierte Paketverluste.
  • Uhrendisziplin: monotone Zähler pro Gerät; vertrauen Sie nie der Systemuhr für die Ordnung.
  • Modellbasierte Tests: zufällige Verflechtungen von Operationen generieren und CRDT‑Invarianten oder LWW‑Ergebnisse behaupten, dann mit dem serverseitigen Endzustand vergleichen.

Sicherheit: Geräte sind ein Perimeter, den Sie nicht kontrollieren

Sync erweitert Ihre Angriffsfläche. Schließen Sie die offensichtlichen Lücken:

  • Pro‑Gerät‑Credentials und Least Privilege: Jedes Gerät erhält einen Scope‑Token, der seine Sync‑Filter enkodiert; Rotation bei Logout/Geräteverlust.
  • Transport: TLS 1.3 auf modernen Geräten erzwingen; 1.2 nur behalten, wenn Sie unbedingt Legacy‑Android unterstützen müssen. Deprecations verfolgen (z. B. veraltete TLS‑1.2‑Schlüsselaustausche werden laut aktuellen IETF‑RFCs abgeschafft) und Upgrades planen.
  • Verschlüsselung at Rest auf dem Gerät: OS‑Keystore‑gestützte Verschlüsselung für lokales SQLite; Wipe bei Jailbreak/Root‑Erkennung oder wiederholtem Attest‑Fehlschlag.
  • Audit: Jeder Merge ist zurechenbar—wer, was, wann, von welchem Gerät. 30–90 Tage Oplog für Forensik aufbewahren; bei Regulierung länger archivieren.

Was einsetzen: Build vs. Buy (und was jeweils tatsächlich leistet)

  • ElectricSQL (Postgres‑zentriert, TypeScript): SQL‑first‑Sync, großartig für Web und Mobile mit vertrauten Tools. Gut, wenn Sie komplett auf Postgres‑Schemata setzen und starke Typisierung wollen.
  • cr-sqlite (CRDT‑Schicht auf SQLite): echtes Multi‑Master auf SQLite via CRDTs; hervorragend für Peer‑to‑Peer oder schwere Offline‑Edits. Sie werden mehr Integrationsarbeit haben.
  • Replicache (client‑fokussiert, web): Optimistic UI, serverseitige Versöhnung. Großartige DX; Sie implementieren die Merges auf dem Server.
  • Realm/Couchbase Lite (mobile‑first, mit Batterien): robuste Mobile‑SDKs mit Konfliktstrategien; höhere Einstiegshürde und anderes Datenmodell als pures SQL.
  • Syncular (neu, TS/Rust‑Kerne): SQL‑Sync mit Offline‑First‑Haltung. Lohnenswert für ein Pilotprojekt, wenn Sie eine TypeScript‑first‑Developer‑Experience mit einem Rust‑Performance‑Kern wollen.
  • LiteFS/Litestream (SQLite‑Replikation): fantastisch für Server‑Failover, nicht für Multi‑Master‑Edits von vielen Geräten. Verwenden Sie diese nicht als mobile Sync‑Schicht.

Entscheidungsheuristik:

  • Wenn Ihre Source of Truth Postgres ist und Sie SQL‑Schemata End‑to‑End wollen, starten Sie mit ElectricSQL‑artigen Ansätzen.
  • Wenn Sie viele gleichzeitige Offline‑Edits und Peer‑to‑Peer‑Szenarien erwarten, setzen Sie auf CRDT‑gestütztes SQLite (cr-sqlite).
  • Wenn Sie Web‑UX und Optimistic Updates mit benutzerdefinierter Serverlogik priorisieren, passen Replicache‑Muster gut.
  • Wenn Sie einen Mobile‑first‑Managed‑Pfad wollen und ein neues Datenmodell akzeptieren können, reduzieren Realm/Couchbase Lite den Aufwand.

Ein 30‑60‑90‑Rollout, der Ihren Betrieb nicht zum Schmelzen bringt

Tag 0: Ziehen Sie Ihren Blast‑Radius

  • Wählen Sie eine Tabelle, die Ihren schwersten Offline‑Edit‑Flow repräsentiert, aber kein Geld ist (z. B. Arbeitsaufträge, Notizen).
  • Definieren Sie SLOs und instrumentieren Sie Client und Server.

Tage 1‑30: MVS (minimal viable sync) ausliefern

  • Lokales Oplog, Versionsvektoren, Batch‑Push/Pull und LWW‑Merges für die Pilot‑Tabelle implementieren.
  • Initiale Sync‑Größe limitieren und pro‑Gerät‑Credentials hinzufügen.
  • Chaos fahren: Zeitskew, Neuordnung, Duplikate. P95‑Konvergenz unter 120 Sekunden anpeilen.

Tage 31‑60: Konfliktpräzision und Migrationen hinzufügen

  • CRDTs oder domänenspezifische Merges für die 20 % der Felder ergänzen, die zählen (Zähler, Mengen).
  • Schema‑Versionsgates einführen und eine sichere additive Migration mit Dual‑Writes durchführen.
  • Selektive Sync‑Filter starten (Teams, Routen).

Tage 61‑90: Härten und skalieren

  • Merges aus Ihrem primären DB‑Connection‑Pool in einen dedizierten Service mit Queues und Rate‑Limits verlagern.
  • Feld‑level‑Verschlüsselung für sensible Spalten einführen, falls nötig.
  • Auf 10–20 % der Produktionsnutzer ausrollen; Reconnect‑Fenster und Backlog‑Gauges beobachten. Batch‑Größen und Backpressure tunen.

In jeder Phase muss der Fehlermodus gleich bleiben: Konvergenz verzögert, niemals Korruption oder Datenverlust. Wenn Sie das nicht sicherstellen können, stoppen Sie und fügen Sie mehr Determinismus hinzu, bevor Sie skalieren.

Kosten, die Sie tatsächlich sehen (und wie Sie sie planbar halten)

  • Netzwerk‑Egress: Selektive Synchronisierung spart echtes Geld. Die initiale Sync‑Größe auf 200 MB zu deckeln und Deltas zu verwenden, kann den Egress im Vergleich zu naiven Ganzzeilen‑JSON‑Pulls um 50–70 % senken.
  • CPU für Merges: CRDT‑Merges sind günstig (Vektorrechnung und Mengen‑Ops) im Vergleich zur Konfliktlösung über ganze Dokumentdiffs. Vermeiden Sie Ganzzeilen‑JSON‑Blobs; senden Sie Spaltendeltas.
  • Storage: Oplog‑Aufbewahrung über 30–90 Tage liegt oft unter 10 % der gesamten DB‑Größe, wenn Sie Batches komprimieren und kompakten. Ältere Historie in Cold Storage archivieren.
  • Teamkosten: Rechnen Sie mit 2–4 erfahrenen Engineers in Vollzeit über 2–3 Quartale, um Sync vom Pilot zur Langeweile zu bringen. Nearshore‑Pods in Brazil mit 6–8 Stunden Zeitüberlappung können die Burn‑Rate um 20–30 % senken—bei gleichbleibender Velocity.

Fallstricke, die Offline‑Projekte töten

  • Uhrenkult: sich auf Zeitstempel statt Zähler/Vektoren verlassen. Unter Skew verlieren Sie Writes.
  • Stille Drops: das Oplog nicht dauerhaft persistieren, bevor dem Nutzer ACK gesendet wird. Crash -> Änderung verloren.
  • Schema‑Roulette: Umbenennungen und destruktive Migrationen ohne Versionsgate. Sie lassen Geräte stranden.
  • Attachments überall: Bilder und PDFs im selben Sync‑Kanal wie kritische Daten. Spuren trennen.
  • Alles‑oder‑nichts‑UX: volle Konvergenz erzwingen, bevor der Nutzer weitermachen kann. Die App unter teilweiser Synchronisierung nützlich lassen—mit klaren Indikatoren.

Das Fazit

Offline‑First hat gerade seinen Moment, weil das Ökosystem es in Mainstream‑Stacks endlich handhabbar macht. SQL‑zentrische Synchronisierung (wie sie bei Projekten wie Syncular im Trend liegt) bedeutet, dass Ihr Team das Modell besitzen, es wie jedes andere verteilte System testen und Ihren operativen Korridor eng halten kann. Behandeln Sie Sync als Produkt: minimaler, tragfähiger Protokollkern, Konfliktpräzision dort, wo es zählt, Migrationen, die Geräte nicht stranden lassen, selektive Synchronisierung für Privacy und Kosten—und SLOs, die Sie Ihrem CEO erklären können.

Wichtigste Erkenntnisse

  • Verwenden Sie SQL plus ein Append‑only‑Oplog und Versionsvektoren; vermeiden Sie reine Zeitstempel‑Ordnung.
  • Wenden Sie LWW auf 80 % der Felder an; nutzen Sie CRDTs oder domänenspezifische Merges für Geld, Inventar und Zähler.
  • Migrationsdesign additiv mit Versionsgates; während Cutovers am Ingress/Egress transformieren.
  • Selektive Synchronisierung ist nicht verhandelbar—für Privacy, Kosten und Performance. Initiale Sync‑Größe deckeln.
  • Echte SLOs instrumentieren: P95‑Konvergenz unter 120 s; Konfliktrate unter 0,5 %.
  • Den Rand schützen: Pro‑Gerät‑Credentials, wo möglich TLS 1.3, keystore‑gestützte Verschlüsselung at Rest, Remote‑Wipe.
  • Kapazität für Reconnect‑Spikes planen; Merges per Queues und Rate‑Limits von Ihrer Primär‑DB entkoppeln.
  • Rechnen Sie mit 2–4 Engineers über 2–3 Quartale, um Sync langweilig zu machen; Nearshore‑Pods können Kosten mit 6–8 Stunden Overlap um 20–30 % senken.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation