10 points par GN⁺ 2025-09-23 | 1 commentaires | Partager sur WhatsApp
  • 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

 
GN⁺ 2025-09-23
Avis Hacker News
  • On présente les CRDT (Conflict-Free Replicated Data Types) comme la solution, mais en pratique il est vraiment difficile de construire un modèle CRDT qui respecte à la fois les attentes intuitives des utilisateurs et une logique métier cohérente, et devoir transformer le modèle de données en paquets de messages puis reconstruire en permanence l’état réel est un énorme casse-tête
    • Il existe une nouvelle initiative de standard web appelée BRAID. Elle vise un standard de synchronisation de l’état du web, en appliquant les transformations opérationnelles (OT) et les techniques CRDT à HTTP pour créer un web synchronisé fondamentalement plus convivial pour les humains comme pour les machines. Braid améliore les performances réseau et prend en charge le P2P natif, l’édition collaborative et le développement de webapps local-first. Liens associés : réunion BRAID, discussion HN sur Braid, discussion sur les API RESTful, article explicatif sur Braid HTTP
    • Les CRDT sont souvent présentés comme une solution universelle, mais en réalité la fusion automatique n’a rien de simple. Techniquement, un algorithme « last writer wins » peut aussi être considéré comme un CRDT, mais pour une fusion de texte complexe, respecter à la fois l’intention de l’utilisateur et ses attentes relève d’un problème presque impossible. Dans certaines situations, tenter une fusion via CRDT peut même être la mauvaise approche. Par exemple, si deux personnes réservent en même temps la même salle de réunion, ce n’est pas à l’algorithme de trancher : il faut que les utilisateurs constatent eux-mêmes le conflit et le résolvent
    • Je suis d’accord pour dire que c’est un domaine difficile à aborder si on n’a pas le goût du risque. Il existe aussi une alternative « sans CRDT » pour ceux qui préfèrent éviter ça ; voir ici
    • Notre équipe construit des apps local-first en choisissant simplement d’ignorer les situations de conflit. La dernière modification l’emporte. La plupart des conflits sont mineurs (ou se règlent facilement via un journal d’audit), et beaucoup ne peuvent de toute façon pas être résolus automatiquement. Par exemple, dans un gestionnaire de tâches avec support hors ligne, si deux personnes démarrent la même tâche en même temps, cela doit être traité au niveau du processus métier
  • Avant, presque tous les logiciels étaient local-first, et cela allait de soi. Mais aujourd’hui, le monde fonctionne entièrement autour du contrôle et de l’optimisation du profit, ce qui crée une structure où les gens se font plus souvent léser. Et même quand cela les agace, ils n’ont pas vraiment d’alternative
    • À l’époque où je fabriquais des produits on-premise et auto-hébergés, la principale plainte des clients était l’absence d’option cloud. La plupart des entreprises ne veulent pas d’auto-hébergement et préfèrent payer un abonnement mensuel pour déléguer ça à quelqu’un d’autre. J’ai l’impression que HN sous-estime fortement la demande réelle pour les services cloud
    • L’idée selon laquelle « si les gens voulaient des services qui les exploitent moins, il serait possible d’en faire un business » n’est pas économiquement juste. Le problème, c’est que les gens tolèrent effectivement un certain niveau de préjudice. Cela pourrait changer avec plus d’éducation ou une meilleure perception du risque, mais à mon avis c’est un problème extrêmement difficile à résoudre
    • Une alternative possible serait le FOSS (logiciel open source)
  • J’aimerais que les apps ne dépendent pas de tout leur contenu uniquement en ligne. Même le GPS de Tesla ne met pas en cache les tuiles déjà téléchargées, si bien qu’hors ligne la carte n’affiche rien. Des apps comme Peacock ou Kanopy ne gardent pas non plus la liste des médias ni les objets rendus sur l’appareil. Or l’appareil possède déjà 95 % du contenu ; j’aimerais qu’on l’exploite activement. Il suffit de marquer l’UI comme dirty en attendant la réussite d’un enregistrement asynchrone. Pas besoin de révolutionner la conception des apps hors ligne : avec de meilleures habitudes, la plupart des problèmes seraient faciles à résoudre
    • Utiliser correctement Cache-Control dans 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
    • Google Maps permet de télécharger manuellement des zones pour un usage hors ligne, et même de mettre plusieurs régions en cache à la fois. Je l’ai bien utilisé hors ligne lors de visites dans des parcs nationaux
    • À l’argument selon lequel « il n’est pas nécessaire de modifier la conception des apps », je pense que l’objectif réel des entreprises est de collecter davantage de données. Apple, par exemple, proposait aussi des cartes hors ligne mais faisait volontairement expirer les données pour maintenir les utilisateurs captifs. Je soupçonne une intention cachée similaire pour les tuiles cartographiques de Tesla (ou de Google)
  • En se concentrant sur des sujets « politiquement chauds » comme le caractère local-first ou distribué des apps, on rate souvent la proposition de valeur essentielle que les gens veulent réellement
    • En passant à Immich, je pensais faire un compromis à cause de l’auto-hébergement, mais j’ai été surpris de voir que c’était largement meilleur qu’Apple ou Google. C’est un produit rare, presque une licorne
  • Je pense qu’au fond, le manque de popularité des apps local-first est un problème économique. Les modèles SaaS ou financés par la publicité sont bien établis, alors que les apps local-first sont nettement moins rentables. Les personnes qui préfèrent ce modèle accordent de l’importance à des caractéristiques comme la souveraineté des données, le chiffrement de bout en bout et l’usage hors ligne, qui entrent en conflit avec les modèles économiques dominants. Au final, on n’a souvent d’autre choix que de compter sur la passion de la communauté open source
    • Désormais, les seules options sont « payer avec de l’argent + des données » ou « regarder des publicités », et un modèle où l’on paie uniquement en vrai argent tout en protégeant ses données est de fait écarté
    • Je développe moi aussi une app local-first appelée Relay, qui ajoute une collaboration façon Google Docs à Obsidian. Je trouve son modèle économique assez original. Le service est séparé entre une « couche d’identité globale » et un « Relay Server » (open source / auto-hébergé), ce qui permet aux utilisateurs de garder un contrôle total sur le contenu de leurs documents. Cela fournit un SSO simple et une gestion des permissions, et suscite particulièrement de l’intérêt chez des entreprises dans l’IA, l’AI Safety ou celles pour qui la conformité est importante. Lien : Relay.md
    • Un cas que je vois souvent autour de moi, ce sont des consommateurs qui renoncent à acheter parce qu’on ne leur propose qu’un abonnement. Ils veulent acheter maintenant et utiliser plus tard, mais des contraintes comme une période de remise limitée ou un prix plus élevé au retour finissent par tuer toute envie d’achat. Je ne pense pas que ce soit le meilleur modèle économique
    • Je ne pense pas que le problème vienne des structures de données répliquées. Même des jeux solo, entièrement local-first, exigent souvent une connexion Internet à cause du launcher
    • Les apps local-first souffrent aussi d’un vrai problème de complexité. Il faut qu’elles fonctionnent sur toutes sortes d’appareils et d’environnements, alors qu’une app cloud-first n’a à tourner que dans un environnement unique côté serveur ; c’est donc relativement plus simple et moins coûteux à maintenir
  • Aujourd’hui, on traite parfois les logiciels desktop et mobiles comme une exception étrange, alors que cela reste un mode de distribution logicielle extrêmement courant. À l’inverse, si l’on essaie d’implémenter des fonctionnalités local-first dans le navigateur, on hérite surtout des inconvénients du navigateur, notamment les problèmes d’intégration avec le système hôte
  • Je ne sais pas si je rate quelque chose, mais j’ai plutôt l’impression qu’en général les apps « local-first » sont la norme. La plupart des utilisateurs utilisent aussi beaucoup d’apps qui reposent sur le hors ligne. Si vous voulez dire « webapps local-first », alors cela me paraît plus juste. En réalité, le concept même de « webapp local-first » est contradictoire
    • J’aimerais bien demander si la plupart des apps sont encore vraiment local-first au sens où on les utilise en payant directement pour elles. En dehors des jeux, j’ai l’impression qu’il n’existe presque plus d’entreprises de ce type, et même les jeux solo exigent désormais Internet sous prétexte de DRM, d’anti-triche ou de mises à jour
    • Ici, « local-first » désigne des apps qui prennent les données locales comme base, plutôt que le stockage cloud, tout en prenant en charge la synchronisation avec le cloud
  • Même les apps offline-first ne sont pas si différentes dès qu’une connexion réseau instable fait tourner un spinner de chargement. Par exemple, Google Docs se bloque en essayant de vérifier si le document est à jour, et ne s’ouvre instantanément que si l’on coupe carrément la connexion avec le mode avion. Spotify se fige aussi en essayant de récupérer des informations annexes en ligne, même pour une playlist déjà enregistrée. Au final, une connexion instable reste le plus gros casse-tête du développement d’apps hors ligne, parce que les apps essaient toujours d’accéder encore une fois aux données du cloud
  • La solution proposée dans l’article reste elle aussi enfermée dans une offre cloud fermée. Comme Firebase, ce n’est pas mauvais en soi, mais c’est regrettable que cela ne soit pas indiqué clairement et qu’on le présente plutôt comme « juste une extension sqlite » alors que seuls des clouds commerciaux sont pris en charge. Des fournisseurs comme Powersync ou ElectricSQL ont au moins le mérite d’être transparents sur ce point, et Powersync permet même l’auto-hébergement
    • Je ne sais pas bien si le concept de local-first peut vraiment s’appliquer aux outils pour développeurs. Il faudrait examiner s’il est possible de construire des logiciels basés sur un modèle de stockage local avec des outils du type SQLite-sync. ElectricSQL peut être auto-hébergé, et je devrais sans doute continuer à mettre à jour ma liste d’outils « sqlite sync ». Liens associés : article original sur le local-first, SQLSync, SQLiteSync, SQLite-Sync
  • Je pense qu’il nous faut davantage d’apps purement locales et auto-hébergées. Ou bien une structure fédérée pourrait aussi convenir. J’ai longtemps eu l’impression que l’infrastructure réseau était l’obstacle principal, mais avec l’arrivée de solutions comme Tailscale, ce genre d’apps va devenir bien plus simple à réaliser
    • Je travaille sur un logiciel de présentation qui doit absolument très bien fonctionner en local, tout en restant accessible de partout. Réunir ces deux exigences en même temps est plus difficile qu’il n’y paraît. Mais avec les progrès techniques, les connexions directes et les implémentations P2P comme WebRTC deviennent plus faciles. Les intégrer à un vrai produit et les tester reste encore un défi. Cela dit, je pense qu’on verra de plus en plus de logiciels à la fois local-first et excellents en réseau. C’est open source. Voir mon profil pour plus d’infos
    • J’explore aussi ce sujet avec intérêt en ce moment. Plus de détails ici. Construire des apps d’une nouvelle manière est assez réjouissant