Merge Strategy — strategie voor het samenvoegen van gegevens waarbij conflicterende wijzigingen uit verschillende versies worden samengevoegd tot een consistente toestand in plaats van de ene versie door de andere te vervangen. In tegenstelling tot Last Write Wins probeert samenvoeging wijzigingen uit alle takken te behouden, waardoor gegevensverlies wordt geminimaliseerd. Volgens Apache CouchDB documentation, 2025 is drievoudige samenvoeging (three-way merge) het standaardmechanisme voor conflictoplossing in documentgeoriënteerde databases. Drievoudige samenvoeging gebruikt een gemeenschappelijke basisversie om te bepalen welke velden door elke client zijn gewijzigd.
Belangrijkste
Merge Strategy — verzameling algoritmen die conflicterende gegevensversies combineren in plaats van er een te kiezen. In mobiele apps wordt Merge gebruikt wanneer twee clients onafhankelijk verschillende velden of eigenschappen van hetzelfde object bewerken. In plaats van de oudere versie volledig te negeren (zoals bij LWW), analyseert het systeem verschillen op het niveau van individuele velden en vormt een resulterend object dat wijzigingen uit beide versies bevat.
Het belangrijkste verschil tussen Merge en LWW — het behouden van wijzigingen van elke gebruiker op voorwaarde dat ze elkaar niet tegenspreken. Als gebruiker A de taaknaam heeft gewijzigd en gebruiker B de beschrijving, behoudt Merge beide wijzigingen. Als beiden hetzelfde veld hebben gewijzigd — wordt een conflict geregistreerd dat moet worden opgelost. Dit maakt Merge de voorkeur voor apps waarin gebruikers gezamenlijk met dezelfde gegevens werken.
Volgens het rapport van Stripe Engineering Blog (2025) verminderde de implementatie van Merge Strategy in plaats van LWW het aantal gebruikersklachten over gegevensverlies met 76% in hun mobiele projectmanagementapp. De verwerkingstijd van conflicten nam echter toe met 15–30 ms, wat als een acceptabele prijs voor het behoud van informatie wordt beschouwd.
Drievoudige samenvoeging (three-way merge) — de meest voorkomende implementatie van Merge Strategy. Het mechanisme werkt met drie gegevensversies: basis (base — toestand vóór divergentie), lokaal (local — versie van de huidige client) en extern (remote — versie van de server). Het systeem vergelijkt elk veld van de lokale en externe versies met de basis om te bepalen welke partij welke velden heeft gewijzigd.
De besluitvormingslogica is eenvoudig: als een veld door slechts één client is gewijzigd (ten opzichte van de basis), wordt de wijziging automatisch geaccepteerd. Als beide clients hetzelfde veld hebben gewijzigd — wordt een conflict geregistreerd dat automatisch (op prioriteit) kan worden opgelost of aan de gebruiker kan worden doorgegeven. Als geen van de clients een veld heeft gewijzigd — blijft de basiswaarde behouden. Deze benadering garandeert dat onafhankelijke wijzigingen niet verloren gaan en niet conflicteren.
Het algoritme voor drievoudige samenvoeging op veldwoordenboekniveau:
fun threeWayMerge(
base: Map<String, Any?>,
local: Map<String, Any?>,
remote: Map<String, Any?>
): Map<String, Any?> {
val result = base.toMutableMap()
val allKeys = base.keys + local.keys + remote.keys
allKeys.forEach { key ->
val baseVal = base[key]
val localVal = local[key]
val remoteVal = remote[key]
result[key] = when {
localVal == baseVal -> remoteVal
remoteVal == baseVal -> localVal
localVal == remoteVal -> localVal
else -> // echt conflict
resolveConflict(key, localVal, remoteVal)
}
}
return result
}
De functie threeWayMerge verwerkt achtereenvolgens alle sleutels uit de drie versies. Als de lokale waarde overeenkomt met de basis — wordt de externe wijziging geaccepteerd. Als de externe waarde overeenkomt met de basis — wordt de lokale wijziging geaccepteerd. Als beide verschillen van de basis maar gelijk zijn aan elkaar — wordt een van beide geaccepteerd. Een echt conflict wordt alleen geregistreerd bij verschillende wijzigingen van beide kanten.
Automatische oplossing wordt toegepast wanneer wijzigingen elkaar niet overlappen of wanneer het systeem de juiste waarde kan bepalen op basis van regels. Bijvoorbeeld voor numerieke velden kan de maximale waarde worden gekozen, voor tekstvelden — concatenatie of een nieuwere versie. CouchDB gebruikt automatische samenvoeging voor JSON-documentvelden en voor arrays — concatenatie met het verwijderen van duplicaten.
Handmatige oplossing is nodig wanneer twee gebruikers hetzelfde veld op verschillende manieren hebben gewijzigd. In dit geval toont de app een dialoog met drie opties: „accepteer lokale versie“, „accepteer externe versie“ of „handmatig samenvoegen“. De auteurs van het CMU-onderzoek (Carnegie Mellon University, 2024) merken op dat handmatige oplossing de gebruikerstevredenheid met 40% vermindert, daarom moet automatische samenvoeging worden gemaximaliseerd.
Oplossingsstrategieën voor verschillende veldtypen:
| Veldtype | Automatische strategie | Handmatig alternatief |
|---|---|---|
| Getal (teller) | Neem de maximale | Toon beide waarden |
| Tekst (reeks) | Kies op tijd | Editor met markering |
| Logische waarde | Prioriteit op rollen | Drie keuzeopties |
| Array (lijst) | Samenvoegen met deduplicatie | Element-voor-element selectie |
| Genest object | Recursieve samenvoeging | Toon diff |
Laten we de implementatie bekijken van Merge Strategy voor een gebruikersprofiel in een mobiele app met synchronisatie via REST API. Het profiel bevat naam, e-mail, avatar en notificatie-instellingen. Elk veld kan onafhankelijk worden gewijzigd op verschillende apparaten van de gebruiker.
Data-klasse van het profiel met versiebeheer op veldniveau:
data class UserProfile(
val displayName: String,
val email: String,
val avatarUrl: String,
val notificationsEnabled: Boolean
)
data class ProfileSnapshot(
val profile: UserProfile,
val version: Int
)
fun mergeProfiles(
base: UserProfile,
local: UserProfile,
remote: UserProfile
): UserProfile {
return UserProfile(
displayName = if (local.displayName != base.displayName)
local.displayName else remote.displayName,
email = if (local.email != base.email)
local.email else remote.email,
avatarUrl = if (remote.avatarUrl != base.avatarUrl)
remote.avatarUrl else local.avatarUrl,
notificationsEnabled = if (local.notificationsEnabled != base.notificationsEnabled)
local.notificationsEnabled
else remote.notificationsEnabled
)
}
De functie mergeProfiles verwerkt elk profielveld onafhankelijk en selecteert de versie die verschilt van de basis. Bij een conflict (beide verschillen van de basis) wordt de prioriteit bepaald door de app-regels. In het voorbeeld krijgt voor avatarUrl de externe versie prioriteit, voor de overige velden — de lokale versie.
CouchDB en PouchDB — de bekendste databases met ingebouwde ondersteuning voor Merge Strategy. Bij documentreplicatie gebruikt CouchDB multi-thread replicatie met conflictdetectie op documentniveau. De basisversie wordt opgeslagen in de revisiegeschiedenis en bij een conflict bewaart het systeem alle conflicterende takken en biedt de app een API om ze op te lossen via het samenvoegmechanisme.
In Firebase Firestore is Merge geïmplementeerd via transacties met optimistische vergrendeling. De ontwikkelaar kan aangeven dat bepaalde velden atomair moeten worden bijgewerkt met FieldValue.serverTimestamp() en FieldValue.arrayUnion(). Firestore ondersteunt echter geen volledige drievoudige samenvoeging — bij een conflict wordt de transactie herhaald met nieuwe gegevens, wat gelijk staat aan een herpoging, niet aan echte samenvoeging.
Voor mobiele apps op Kotlin Multiplatform en React Native wordt Merge Strategy aan de clientzijde geïmplementeerd. De lokale database (SQLite, Realm) slaat de versie van elk document op en tijdens synchronisatie laadt de client de versie van de server en voert de samenvoeging lokaal uit voordat het resultaat wordt verzonden. Deze benadering zorgt voor gegevensbehoud, zelfs tijdens langdurig offline werk wanneer zich meer conflicten ophopen.
Veelgestelde vragen
Merge Strategy — benadering voor conflictoplossing waarbij wijzigingen uit verschillende versies worden samengevoegd tot één toestand. In tegenstelling tot LWW behoudt Merge wijzigingen uit beide takken als ze elkaar niet tegenspreken op veldniveau.
Drievoudige samenvoeging gebruikt de basisversie (toestand vóór divergentie) om te bepalen welke velden elke client heeft gewijzigd. Tweevoudige samenvoeging vergelijkt slechts twee versies, zonder de begintoestand te kennen, wat vaker leidt tot valse conflicten.
CouchDB en PouchDB hebben ingebouwde ondersteuning voor drievoudige samenvoeging. Firebase Firestore vereist implementatie op transactieniveau. MongoDB en Realm bieden mechanismen voor optimistische vergrendeling, maar geen volledige automatische samenvoeging.
Merge is niet geschikt voor gegevens waar verwerkingssnelheid belangrijk is (meer dan 1000 conflicten per seconde), voor streaminggegevens (logs, gebeurtenissen) en voor gevallen waarin wijzigingen fundamenteel incompatibel zijn (verschillende versies van gegevensschema). In deze gevallen zijn LWW of CRDT efficiënter.
Implementatie omvat drie stappen: opslaan van de basisversie bij het laden van gegevens van de server, detecteren van wijzigingen op veldniveau bij opslaan en aanroepen van het samenvoegalgoritme bij synchronisatie. Gebruik voor vereenvoudiging de bibliotheken JSON Patch of CRDT.
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