Sync Engine — is de component van de app die verantwoordelijk is voor het gecoördineerd bijwerken van gegevens tussen de lokale opslag van het apparaat en de externe server. In mobiele apps zorgt Sync Engine voor offline werking, achtergrondsynchronisatie en conflictoplossing. Volgens Google Firebase (2025) laten apps met ingebouwde Sync Engine een 25% hogere retentie zien in regio’s met een onstabiele verbinding.
Belangrijkste punten
Sync Engine — is een architectuurlaag tussen de lokale database en de externe API die de gegevensstroom in beide richtingen beheert. Zijn taken: wijzigingen volgen, naar de server sturen, wijzigingen van de server ontvangen en conflicten oplossen. De gebruiker werkt met lokale gegevens en de Sync Engine synchroniseert ze naadloos met de server.
Sync Engine kan ingebouwd (Firebase Firestore, Couchbase Lite, Realm) of aangepast zijn — geschreven voor specifieke bedrijfslogica. Ingebouwde motoren bieden kant-en-klare offline-first functionaliteit en conflictoplossing. Aangepaste motoren geven volledige controle over het gegevensformaat, synchronisatieprotocol en conflictbeleid.
Volgens Sravan Kartik (2024), auteur van het boek «Mobile Sync Engine Design Patterns», is een aangepaste Sync Engine gerechtvaardigd voor apps met complexe bedrijfslogica (financiën, medisch, IoT), waar aangepaste samenvoegregels cruciaal zijn. Voor typische scenario’s (notities, chats, feeds) zijn ingebouwde Firestore of Realm voldoende.
interface SyncEngine {
suspend fun pull(lastSyncTimestamp: Long): SyncResult
suspend fun push(operations: List<QueuedOperation>): PushResult
suspend fun resolve(conflicts: List<Conflict>): ResolutionResult
fun observeSyncState(): Flow<SyncState>
}
Deze interface beschrijft het minimale contract van Sync Engine: pull (wijzigingen van server ophalen), push (lokale wijzigingen verzenden), resolve (conflicten afhandelen) en observe (synchronisatiestatus bewaken). Deze abstractie maakt het mogelijk de implementatie te wijzigen zonder de presentatielaag aan te passen.
Full sync (volledige synchronisatie) — bij elke sessie wordt de volledige gegevensset van de server geladen. Eenvoudige implementatie, maar onaanvaardbaar voor grote volumes: het laden van 10.000 records bij elke keer dat de app wordt geopend, verbruikt data en batterij. Full sync is gerechtvaardigd voor referentiegegevens (landenlijst) met zeldzame updates.
Incremental sync (incrementele synchronisatie) — alleen records die sinds de laatste synchronisatie zijn gewijzigd, worden verzonden. De server slaat de tijdstempel van de laatste wijziging voor elk record of de hele set op. De client verzendt lastSyncTimestamp en ontvangt alleen records met updated_at > deze waarde. Volgens Instagram Engineering (2024) vermindert incremental sync het gegevensvolume met 97% vergeleken met full sync.
Push sync (server-geïnitieerde synchronisatie) — de server stelt de client zelf op de hoogte van de noodzaak tot synchronisatie via FCM (Firebase Cloud Messaging), WebSocket of SSE (Server-Sent Events). De client verspilt geen middelen aan periodieke polling. Push sync is de optimale oplossing voor realtime apps: chats, meldingen, likes. Google Firebase Firestore gebruikt WebSocket voor realtime synchronisatie met automatische fallback op HTTP polling.
| Type | Dataverbruik | Vertraging | Complexiteit | Toepassing |
|---|---|---|---|---|
| Full sync | Hoog | Hoog | Laag | Referenties, configuraties |
| Incremental | Laag | Laag | Gemiddeld | Feeds, catalogi, profielen |
| Push sync | Minimaal | Minimaal | Hoog | Chats, meldingen, samenwerking |
Hybride aanpak — combinatie van typen: bij het starten van de app full sync voor basisgegevens, daarna incremental sync voor updates en voor kritieke gebeurtenissen — push sync via FCM. Dit biedt zowel snelheid als middelenbesparing.
Checkpoint — een waarde die de client opslaat tussen synchronisatiesessies. Meestal is dit de updated_at van het laatste succesvol gesynchroniseerde record. Bij de volgende synchronisatie stuurt de client het checkpoint naar de server en deze retourneert alle records met updated_at later dan het checkpoint. Cursor-based pagination — een geavanceerde versie waarbij de server een cursor (aanwijzer voor de volgende pagina) samen met de gegevens retourneert.
Delta synchronisatie — de server berekent het verschil tussen de huidige gegevensstatus en de momentopname die de client heeft gezien. In plaats van alle records te verzenden, worden alleen bewerkingen (insert, update, delete) doorgegeven. Dit is bijzonder efficiënt voor grote gegevenssets waar slechts enkele records zijn gewijzigd. Google Drive API (2025) gebruikt changes.list met pageToken voor delta synchronisatie van bestanden.
Strategie van «uitgestelde delta’s» — op de mobiele client worden wijzigingen niet onmiddellijk verzonden, maar gebufferd in de Offline Queue. Bij het bereiken van een drempel (10 bewerkingen of 30 seconden) wordt een deltapakket gevormd en naar de server gestuurd. Volgens Dropbox Mobile Engineering (2024) verminderde het bundelen van delta’s het aantal HTTP-verzoeken met 65% en verlaagde het batterijverbruik met 12%.
data class SyncCheckpoint(
val lastUpdated: Long,
val pageToken: String?,
val version: Int
)
suspend fun syncIncremental(checkpoint: SyncCheckpoint): SyncResult =
api.pullChanges(
since = checkpoint.lastUpdated,
token = checkpoint.pageToken
)
SyncCheckpoint slaat zowel de tijdstempel als de paginacursor op voor lange lijsten. Twee-parameter checkpoint garandeert dat geen enkel record wordt overgeslagen of gedupliceerd tijdens synchronisatie van grote gegevenssets.
WebSocket — een permanente tweerichtingsverbinding tussen client en server. De server stuurt direct updates zodra gegevens veranderen. WebSocket is optimaal voor realtime apps: chats, streaming, samenwerkend werk. Nadeel: batterij- en dataverbruik voor het in stand houden van de verbinding (heartbeat). OkHttp WebSocket op Android en URLSessionWebSocketTask op iOS zijn ingebouwde implementaties.
Firebase Cloud Messaging (FCM) — pushmeldingen die de server niet stuurt om aan de gebruiker te tonen, maar om synchronisatie te activeren. Bij ontvangst van een silent push (data message) wordt de app geactiveerd en start de Sync Engine. FCM vereist geen permanente verbinding en is zuiniger dan WebSocket voor zeldzame meldingen.
SSE (Server-Sent Events) — een eenrichtingskanaal waarmee de server gebeurtenissen naar de client stuurt. Eenvoudiger te implementeren dan WebSocket, maar ondersteunt geen tweerichtingscommunicatie. EventSource API (JavaScript) en OkHttp SSE (Android) zijn populaire bibliotheken. SSE is geschikt voor meldingen over nieuwe gegevens wanneer de client geen gegevens terug hoeft te sturen via hetzelfde kanaal.
Volgens WhatsApp Engineering (2024) gebruikt hun Sync Engine een combinatie van WebSocket voor actieve sessies en FCM om de app op de achtergrond te activeren: WebSocket wordt na 5 minuten inactiviteit verbroken en volgende updates worden via silent push afgeleverd.
Snapshot-based sync — de server maakt periodiek een volledige momentopname (snapshot) van de gegevens en kent er een versie aan toe. De client slaat het huidige versienummer op. Als het verouderd is — laadt het een nieuwe momentopname. Dit is een eenvoudige en betrouwbare strategie, maar inefficiënt voor frequente wijzigingen — elke keer wordt de volledige gegevensset geladen.
Versiebeheer op recordniveau — elk record heeft een version-veld. Tijdens synchronisatie stuurt de client de versies van alle records en de server retourneert alleen records waarvan de versie is gewijzigd. Dit is efficiënter dan snapshot sync, maar vereist het opslaan van versies op de client. Vector Clocks — een geavanceerde techniek voor gedistribueerde systemen, waarbij elk knooppunt zijn eigen versie toewijst en conflicten worden opgelost op basis van gedeeltelijke ordening.
Snapshot met incrementele diff — hybride aanpak: zeldzame volledige snapshot (eenmaal per dag) + incrementele sync daartussen. Na lange afwezigheid laadt de client de snapshot en bij frequente synchronisaties alleen delta’s. Git-achtige aanpak — elke gegevenscommit heeft een hash en de client weet van welke commit hij moet uitgaan. Dit is geïmplementeerd in Couchbase Lite Sync Gateway (2024) en is een betrouwbaarheidsstandaard.
data class VersionedEntryT(
val id: String,
val data: T,
val version: Long,
val deleted: Boolean
)
fun SyncEngine.resolveVersion(local: VersionedEntry*, remote: VersionedEntry*): VersionedEntry* =
when {
local.version > remote.version -> local
remote.version > local.version -> remote
else -> resolveConflict(local, remote)
}
Regel voor versieoplossing: als versies overeenkomen — geen wijzigingen. Als de lokale versie nieuwer is — wint de lokale. Als de serverversie nieuwer is — wint de server. Alleen bij gelijke versies maar verschillende gegevens — wordt de conflict resolver aangeroepen. Last Write Wins met version-vlag — de eenvoudigste maar betrouwbare strategie.
Stap 1: Datamodel definiëren — welke entiteiten worden gesynchroniseerd, hoe vaak veranderen ze, wat is het volume. Voor elke entiteit een strategie (incremental / full / push) en toegestane synchronisatievertraging vaststellen.
Stap 2: Protocol kiezen — REST met checkpoints, GraphQL met Subscriptions of gRPC met bidirectionele stream. GraphQL Subscriptions — een populaire keuze voor moderne apps: één protocol voor zowel pull als push. Apollo Client (2025) ondersteunt offline synchronisatie via cache op het apparaat.
Stap 3: Offline Queue implementeren — lokale opslag van wijzigingen met idempotency-sleutels (zie artikel «Offline Queue»). De wachtrij is de basis van een betrouwbare Sync Engine: zonder deze garandeert synchronisatie geen levering van wijzigingen.
Stap 4: Conflict resolver kiezen — LWW voor eenvoudige gevallen, CRDT voor gezamenlijk bewerken, Custom merge voor bedrijfslogica. Regel: de resolver moet idempotent zijn — het herhaald toepassen van dezelfde bewerking moet hetzelfde resultaat geven.
Stap 5: Monitoring en metrieken — elke synchronisatie loggen: aantal records, uitvoeringstijd, aantal conflicten, fouten. Firebase Crashlytics of Sentry (2025) maken het mogelijk synchronisatiefouten in realtime te volgen.
Volgens Realm Team (2024) verwerkt een typische Sync Engine voor mobiele apps 100–500 synchronisaties per dag per apparaat, met gemiddeld 50–200 KB aan gegevens per sessie. Protocoloptimalisatie — Protobuf-compressie in plaats van JSON — vermindert het gegevensvolume met nog eens 40–60%.
Veelgestelde vragen
API-client voert afzonderlijke verzoeken uit en retourneert resultaat. Sync Engine beheert de gegevensstatus: volgt wijzigingen, buffert ze offline, synchroniseert op de achtergrond en lost conflicten op. Sync Engine = API-client + lokale database + wachtrijbeheerder + conflict resolver.
Optimale frequentie hangt af van het gegevenstype: kritiek (berichten, bestellingen) — via push sync in realtime; niet-kritiek (feed, meldingen) — incremental sync elke 15–30 minuten. WorkManager PeriodicWorkRequest maakt het mogelijk het interval op Android in te stellen met inachtneming van Doze Mode.
Automatische strategie — Last Write Wins (op basis van server tijdstempel). Als dit onaanvaardbaar is — CRDT of aangepaste samenvoeging op de server. In laatste instantie — beide versies bewaren en de gebruiker laten kiezen. Hoofdregel: nooit gebruikersgegevens verliezen bij conflictoplossing.
Firebase Firestore — de beste keuze voor typische apps (chats, feeds, sociale netwerken). Het biedt offline-first, realtime synchronisatie en conflictoplossing «uit de doos». Aangepaste Sync Engine is gerechtvaardigd bij specifieke bedrijfslogica, privacyvereisten of integratie met een legacy-server.
Autotests — mock-server met voorspelbare antwoorden, testen van Offline Queue en conflict resolver. Integratietests — echte server in testomgeving, simulatie van netwerkvertragingen met Network Less Tool. E2E-tests — twee apparaten die via één account synchroniseren, controle van gegevensconsistentie na een reeks bewerkingen.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook