<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mathéo Delbarre</title>
    <description>The latest articles on DEV Community by Mathéo Delbarre (@etoile_bleu).</description>
    <link>https://dev.to/etoile_bleu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3984106%2F1a0896d3-ec34-45da-af5b-6c62036750a0.png</url>
      <title>DEV Community: Mathéo Delbarre</title>
      <link>https://dev.to/etoile_bleu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/etoile_bleu"/>
    <language>en</language>
    <item>
      <title>Simulating 2G to build an offline-first sync engine in Rust for rural clinics</title>
      <dc:creator>Mathéo Delbarre</dc:creator>
      <pubDate>Sun, 14 Jun 2026 16:11:46 +0000</pubDate>
      <link>https://dev.to/etoile_bleu/simulating-2g-to-build-an-offline-first-sync-engine-in-rust-for-rural-clinics-38bd</link>
      <guid>https://dev.to/etoile_bleu/simulating-2g-to-build-an-offline-first-sync-engine-in-rust-for-rural-clinics-38bd</guid>
      <description>&lt;p&gt;hey dev.to,&lt;/p&gt;

&lt;p&gt;so I am Mathéo, a 2nd year CS student at EPITECH Nancy (France). I want to share a project I have been building for the last few months: &lt;strong&gt;ZamSync&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Basically, it is a lightweight synchronization engine written in Rust. It is made for places where the internet is either extremely slow, drops every five minutes, or does not exist at all (think remote areas, Raspberry Pi nodes, offline-first apps).&lt;/p&gt;

&lt;p&gt;The exact scenario I had in mind is the electronic Patient Information System (ePIS) of Bhutan. In rural Bhutan, district clinics need to register patients and sync the data back to central hospital hubs. The problem is the network: they often have 2G connections, 600ms latency, and constant cuts. &lt;/p&gt;

&lt;p&gt;I looked at existing tools, but they either require a permanent stable connection or need a heavy database engine running on the client. I wanted to build something that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Works over days of total disconnection.&lt;/li&gt;
&lt;li&gt;Recover instantly if the network drops mid-sync (without duplicating data).&lt;/li&gt;
&lt;li&gt;Runs on tiny hardware (under 10MB of RAM on a Raspberry Pi).&lt;/li&gt;
&lt;li&gt;Keeps everything secure (encrypted at rest and in transit).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the GitHub repository if you want to inspect the code:&lt;br&gt;
&lt;a href="https://github.com/Etoile-Bleu/ZamSync" rel="noopener noreferrer"&gt;https://github.com/Etoile-Bleu/ZamSync&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How it works under the hood
&lt;/h2&gt;

&lt;p&gt;The engine is built around a simple principle: append-only logs. &lt;/p&gt;

&lt;p&gt;Instead of syncing a database state directly, ZamSync syncs &lt;strong&gt;events&lt;/strong&gt; (which can carry JSON payloads, like patient check-ins). &lt;/p&gt;

&lt;p&gt;Here is the technical stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write-Ahead Log (WAL):&lt;/strong&gt; Events are written locally to an encrypted, append-only file. Each record has a CRC32 integrity check to prevent corruption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Logical Clocks (HLC):&lt;/strong&gt; Since clinics do not have reliable NTP servers to sync their system clocks, we use HLCs to order events deterministically across different nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Vectors:&lt;/strong&gt; When two nodes connect, they exchange their version vectors (essentially a map of who has seen what sequence number). They compare them, find the exact gaps, and only send the missing events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WAL Encryption:&lt;/strong&gt; The log file is encrypted at rest using ChaCha20-Poly1305. A random 96-bit nonce is generated for every single record, and keys can be rotated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mTLS (mutual TLS):&lt;/strong&gt; The network layer uses custom mTLS certificates signed by the hub CA. If a node does not have a valid signed certificate, it is rejected during the TLS handshake before any data can be read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also implemented a &lt;code&gt;--policy own&lt;/code&gt; access control. If Clinic A and Clinic B both sync to the same Hospital Hub, Clinic A cannot download the events submitted by Clinic B. The hub keeps everything, but restricts sync replies based on the client certificate identity.&lt;/p&gt;


&lt;h2&gt;
  
  
  Simulating the 2G network with Toxiproxy
&lt;/h2&gt;

&lt;p&gt;To verify if this actually works in real-world conditions, I did not want to just write standard unit tests on localhost. &lt;/p&gt;

&lt;p&gt;I set up a test suite using Docker Compose and &lt;strong&gt;Toxiproxy&lt;/strong&gt; (an awesome tool by Shopify to simulate network failure). The test setup does this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Starts a hub node and a client node.&lt;/li&gt;
&lt;li&gt;Interposes Toxiproxy between them.&lt;/li&gt;
&lt;li&gt;Sets the link to emulate a bad rural 2G network: 600ms latency, 100ms jitter, 30 KB/s bandwidth cap.&lt;/li&gt;
&lt;li&gt;Generates 5,000 events.&lt;/li&gt;
&lt;li&gt;In the middle of the transfer, the test script cuts the connection completely for a few seconds.&lt;/li&gt;
&lt;li&gt;Reconnects and runs the sync again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the end, all 5,000 events are replicated with zero loss, zero duplicates, and no corrupted states.&lt;/p&gt;

&lt;p&gt;If you have Docker installed, you can run this test yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; tests/docker-compose.test.yml up &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nt"&gt;--abort-on-container-exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The codebase structure
&lt;/h2&gt;

&lt;p&gt;The project uses a clean Rust workspace split into 4 crates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;zamsync-core&lt;/code&gt;: Pure state logic, events, HLCs, and ports. No I/O.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zamsync-storage&lt;/code&gt;: The engine implementation and the WAL filesystem code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zamsync-network&lt;/code&gt;: The network layer, TCP transport, frame format, and mTLS logic.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zamsync-testing&lt;/code&gt;: Helper tools and integration tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also cross-compile static musl binaries for &lt;code&gt;x86_64&lt;/code&gt;, &lt;code&gt;aarch64&lt;/code&gt; (Raspberry Pi 4), and &lt;code&gt;armv7&lt;/code&gt; (Raspberry Pi 3) so that installing it on remote Linux machines is just a curl command with no library dependencies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Next steps &amp;amp; feedback
&lt;/h2&gt;

&lt;p&gt;This is my first time building a low-level sync engine in Rust, and I would love to get feedback from other systems engineers. &lt;/p&gt;

&lt;p&gt;Does the WAL approach make sense for this use case? Are there edge cases in my Version Vector implementation that I might have missed?&lt;/p&gt;

&lt;p&gt;If you want to check the architecture or play with the CLI, here is the link:&lt;br&gt;
&lt;a href="https://github.com/Etoile-Bleu/ZamSync" rel="noopener noreferrer"&gt;GitHub - Etoile-Bleu/ZamSync&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mathéo&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>architecture</category>
      <category>networking</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
