- Les apps local-first promettent une réactivité rapide et une protection de la vie privée par défaut, mais elles se heurtent en pratique à la grande difficulté de mettre en œuvre un véritable support hors ligne
- La raison principale est la complexité de la synchronisation : lorsque plusieurs appareils modifient les données en même temps, ils doivent au final converger exactement vers le même état
- Deux grands défis techniques se posent : l’incertitude sur l’ordre temporel et les conflits
- Pour résoudre ce problème, il faut appliquer des approches de systèmes distribués comme les Hybrid Logical Clocks(HLCs) et les CRDTs
- En s’appuyant sur des extensions basées sur SQLite, il est possible de proposer une architecture de synchronisation simple et fiable, exploitable sur toutes les plateformes
La promesse et la réalité des apps offline-first
- Les apps offline-first mettent en avant une réponse instantanée, une protection de la vie privée par défaut et une utilisation sans attente de chargement, même dans un environnement réseau instable
- En réalité, la plupart des apps n’implémentent pas correctement le support hors ligne, et la majorité se contente de stocker temporairement les changements en local avant de les envoyer plus tard lorsqu’une connexion réseau est disponible
- Ce type d’implémentation est peu fiable et finit par conduire à des messages d’avertissement du type : « il se peut que les modifications ne soient pas enregistrées »
La difficulté fondamentale de la synchronisation
- Construire une app local-first revient inévitablement à mettre en place un système distribué
- Plusieurs appareils peuvent modifier les données indépendamment en mode hors ligne et, lorsqu’ils se reconnectent plus tard, ils doivent converger précisément vers le même état
- Cela implique deux grands défis
- L’incertitude sur l’ordre des événements
- Les conflits sur une même donnée
1. L’incertitude sur l’ordre des événements
- Des événements se produisent à des moments différents sur plusieurs appareils, et l’état final peut varier selon l’ordre appliqué
- Exemple : l’appareil A définit x=3, l’appareil B définit x=5 → après des modifications effectuées hors ligne de part et d’autre, la synchronisation peut produire des résultats différents
- Les bases de données centralisées classiques résolvent cela avec une cohérence forte, mais cela exige une synchronisation globale, ce qui ne convient pas aux systèmes local-first
- Il faut donc, au final, déterminer le bon ordre pour chaque événement, même dans un environnement dynamique et distribué ; il faut une manière de fixer l’ordre sans horloge centrale
Introduction des Hybrid Logical Clocks(HLCs)
- Les Hybrid Logical Clocks(HLCs) sont un algorithme simple mais efficace qui permet aux appareils de s’accorder concrètement sur l’ordre des événements
- Un HLC combine des informations de temps physique et un compteur logique
- Par exemple :
- l’appareil A enregistre un événement à 10:00:00.100, le HLC vaut (10:00:00.100, 0)
- l’appareil B, qui reçoit le message, augmente le HLC à (10:00:00.100, 1), même si sa propre horloge est en retard
- cela permet de déterminer correctement l’ordre des événements, indépendamment de l’écart entre les horloges physiques des deux appareils
2. Le problème des conflits
- Appliquer le bon ordre ne suffit pas : si plusieurs appareils modifient indépendamment la même donnée, des conflits surviennent inévitablement
- La plupart des systèmes demandent au développeur d’écrire manuellement le code de résolution des conflits, ce qui entraîne des risques d’erreur et une charge de maintenance
Utilisation des CRDTs
- La meilleure approche consiste à utiliser des Conflict-Free Replicated Data Types(CRDTs)
- Les CRDTs garantissent que quel que soit l’ordre de synchronisation, ou même en cas d’applications en double, l’état de chaque appareil finit toujours par être identique
- La stratégie CRDT la plus simple est le Last-Write-Wins(LWW)
- chaque mise à jour reçoit un horodatage
- lors de la synchronisation, la valeur portant l’horodatage le plus récent est retenue
Les avantages de SQLite
- Pour construire une app local-first, il est indispensable de disposer d’une base locale légère et fiable, et SQLite est le meilleur choix
- L’implémentation de la synchronisation via des extensions de framework basées sur SQLite offre les avantages suivants
- l’application d’un message est simple : lire la valeur actuelle → si le nouvel horodatage est plus récent, écraser → sinon, ignorer
- cette approche garantit la convergence de l’état sur tous les appareils, indépendamment de l’ordre de synchronisation
L’intérêt de cette architecture
- Cette structure permet une synchronisation simple et fiable
- une fiabilité sans perte de données, même après plusieurs semaines hors ligne
- une propriété déterministe de convergence systématique vers l’état final
- une solution reposant uniquement sur une extension SQLite légère, sans dépendances lourdes
- prise en charge de toutes les principales plateformes : iOS, Android, macOS, Windows, Linux, WASM, etc.
Recommandations aux développeurs
- Il faut éviter les approches qui se contentent de « simuler » un mode hors ligne avec une simple file de requêtes
- Il faut adopter le concept d’eventual consistency et s’appuyer sur des technologies éprouvées des systèmes distribués comme les HLC et les CRDT
- Mieux vaut privilégier une architecture petite et sans dépendances plutôt que de gros frameworks complexes
- Au final, l’app peut bénéficier d’atouts comme une exécution immédiate, un usage hors ligne et une protection de la vie privée par défaut
Référence à l’open source SQLite-Sync
- Si vous cherchez un moteur offline-first open source, multiplateforme et prêt pour la production, vous pouvez consulter l’extension SQLite-Sync
1 commentaires
Avis Hacker News
Cache-Controldans les réponses API et le faire respecter par la couche réseau permet de résoudre beaucoup de problèmes. Cela permet aussi de modifier la durée de vie du cache côté serveur sans mise à jour de l’app