How multi-platform synchronization is implemented
1) What is multi-platform synchronization and why it is needed
Multi-platform synchronization is the consistent update of the same data on different devices and clients: mobile applications (iOS/Android), web/PWA, desktops and integrations (bots, mini-applications). Objectives:- Continuity - Continue from the same location on any device.
- Offline resistance: work without a network and safely "catch up" the server.
- Product speed: Minimum delays between the action and the appearance of the result everywhere.
2) Basic architecture (skeleton)
1. Single domain model: clear entities (user, wallet/balance, transaction, settings, favorites, etc.) and their connections.
2. Synchronization server: API gateway (REST/GraphQL), versioning layer, event log.
3. Clients: local database (SQLite/Room/Core Data/Realm/IndexedDB), static resource cache (App Shell), outbox for offline operations.
4. Transport: read/write requests + push-disability channels (WebSocket, SSE, mobile fluffs) for notification of new versions.
5. Identification and access: OIDC/OAuth2 + short-lived tokens (access) and rotation of refresh tokens.
6. Observability: sinka logs, metrics, alerts.
3) Data model and versioning
Global versions: 'updated _ at '/' version' on each object, monotonously growing.
Incremental feeds: 'GET/changes? since = cursor 'returns delta of changes.
ETag/If-None-Match: Saves traffic on unchanged resources.
Shadow state: The client stores the last known version for comparison and merge.
4) Offline pattern: outbox + idempotency
Any write action falls into the outbox with a temporary'client _ id ', time, operation type, and request body.
Sending in batches with exponential backoff on errors.
Idempotency: in the header/endpoint - operation key ('Idempotency-Key'). Replay will not create takes.
Atomicity: adding to outbox and local update - in one database transaction.
5) Merge conflicts and strategies
LWW (Last Write Wins): simple and fast; risk of loss of edits, suitable for settings/likes/flags.
Versioning/Precondition: the server rejects obsolete records ('412 Precondition Failed') → the client shows the diff and offers to overwrite/merge.
OT (Operational Transform): for texts/joint editing.
CRDT (Conflict-free Replicated Data Types): for lists, counters, sets; automatic merge without conflicts.
Field policy: "server truth" for money/balances; client true for local labels.
UX in case of conflict: "Solution required" badge, version comparison, "Leave mine/Merge/Reboot" choice.
6) Transport and ways to deliver change
Pull: periodic requests' changes? since = cursor '(cheap and simple).
Push-invalidate: WebSocket/SSE sends a hint about new changes → the client makes a quick pull.
Webhooks: the server notifies third-party services/bots; for customers - better push + pull.
GraphQL Subscriptions: for realtime scripts, while still storing the local cursor.
7) Background tasks and platform limitations
iOS: Background Tasks/Push with content-available; time and energy constraints.
Android: WorkManager/Foreground service for need (battery safe).
PWA: Background Sync/Periodic Sync (nuanced on iOS), Service Worker for cache and offline.
Retries policy: backoff, limits, stop at low battery/roaming (configurable).
8) Security and privacy
Authentication: OIDC/OAuth2, PKCE for public clients.
Encryption in transit: TLS 1. 2/1. 3, strict ciphersuite, HSTS; if possible - certificate pinning in mobile.
Encryption on the device: keys/tokens - in Keychain/Keystore; sensitive data - AES-GCM.
Isolation of environments: dev/stage/prod with different keys, "combat" dataset outside prod is prohibited.
Authorization to the object: server-side verification of rights to each entity in the link (do not trust the client).
Audit log: who changed what and when; needed for financial/regulatory cases.
9) Performance and traffic savings
Deltas instead of full-bodied objects (patch/JSON Patch, GraphQL @ defer/@ stream).
Compression: Brotli/Gzip; binary protocols (MessagePack/Protobuf) for chat/telemetry.
Cursors and pagination: 'limit/next _ cursor', no heavy "all at once."
Event Coalescence: Combine frequent small changes (debounce) before sending.
Cache control: reasonable TTL and ETag for immutable resources.
10) Observability and synchronization metrics
Sync Success Rate: The proportion of successful sinus cycles.
Time To Consistency (TTC) - the average time for which the change is visible on all active devices.
Conflict Rate и Resolve Time.
Outbox Depth and Middle Age elements.
Payload Size / Session и Retry Count.
Battery Impact (mobile), Data usage.
SLO: e.g. 95% of changes are consistent ≤ 3 seconds online.
11) Testing and chaos scenarios
Network Shaping: 2G/3G, high RTT, losses 1-10%, flapping Wi-Fi.
Kill & Resume: killing the process at the time of the bruise.
Dedloki/competition: parallel edits from two devices under different accounts/roles.
Bulk Schema Migration - Rollback/Redo on Local DB Migration Error.
Security: token spoofing, MITM tests, attempts to re-use idempotent keys.
12) Schema migrations and backward compatibility
Schema versions: 'schema _ version' in the client database; migrations are incremental and rollback-safe.
Forward/Backward API compatibility: add fields non-destructively; old clients ignore the unknown.
Feature flags-Include new data/event types in stages.
Dual-write during server migration + consistency validation.
13) Frequent errors - and quick fixes
"We write immediately to the network, and then offline →" start with an outbox pattern and idempotency.
There are no cursors/deltas → traffic and time are exploding. Enter'changes? since`.
LWW for critical financial data → Use strict invariants, transactions, and business rules on the server.
Hidden Conflicts → Add a custom diff/solver.
Background tasks without limits → land the battery; respect OS policies.
Keeping secrets in clear text → Keychain/Keystore + encryption.
The lack of metrics → it impossible to understand where the "flows." Turn on Telemetry/Tracing with PII sanitizer.
14) Implementation checklist (90 days)
1. Model and Data Map Specification (ERD), choice of merging strategies by entity.
2. Delta API: '/changes? since ', cursors, ETag, pagination.
3. Outbox on clients: transactions, idempotent keys, backoff.
4. Push-invalidate: WebSocket/SSE or push with content-available → fast pull.
5. Local database + migrations (Room/Core Data/Realm/IndexedDB).
6. Security: OIDC, TLS, pinning, encryption on the device, RBAC on the server.
7. Metrics and logs: TTC, conflict rate, outbox depth, retries, battery/data usage.
8. Chaos tests: bad network, kill-resume, conflicts, migrations.
9. UX signals: online/offline/sink statuses, conflict diff, repeat/cancel.
10. Gradual rollout: flags, canaries, filter by region.
15) Mini-FAQ
Pull or push?
Better hybrid: push-invalidate reports "there is new," and then a light pull over the cursor.
CRDT or LWW?
CRDT is more expensive to implement but good for shared editing/lists. For most settings/flags, LWW is enough, for finance - strict server invariants.
How to fit into the battery?
Batches, backoff, group sending, "quiet windows" and disabling aggressive retrays in roaming/low charge.
What to do with offline private data?
Minimize, encrypt, store keys only in Keychain/Keystore; provide for auto-cleaning.
Do I need GraphQL?
Convenient for samples and deltas; but REST with cursors and ETag works great too. The main thing is the discipline of versions and deltas.
Multi-platform synchronization is not one "magic" technology, but a system: a single data model and versioning, offline queue and idempotency, reasonable merge strategies, a push/pull hybrid, background tasks with respect for the battery, strict security and transparent metrics. By implementing these layers sequentially and testing them in chaos scenarios, you will get predictable, fast and secure synchronization on all platforms - without data loss and user nerves.