3.2 KiB
| title | description | date | projectPeriod | thumbnail | tags | selected | featuredOrder | project | role | stack | scale | outcome | audience | links | media | |||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Syncing State with Immutable Tries | How a multi-device life tracking project used trie structure to diff, reconcile, and synchronize goal state. | 2026-05-05 | August-September 2019 |
|
|
true | 3 | towers | Full-stack author |
|
Multi-device goal and task state shared between clients and a server | A working synchronization model built around immutable trie properties | recruiter-relevant |
|
|
Life Towers was a multi-device goal and task tracker with an intentionally visual interface. The surface idea was an aesthetic representation of previous and current goals. The more interesting part was synchronizing state across clients without sending more data than necessary.
This was not a large distributed system, but it had a real version of a common problem: clients and server drift apart, and the system needs a compact way to compare, reconcile, and update.
The Problem
If a task model is stored as an ordinary mutable object graph, synchronizing it often becomes a choice between sending too much data or writing complicated ad hoc diff logic.
I wanted a structure where the shape of the data made synchronization easier. The client should be able to compare its state with the server's state, find a difference, reconcile it, and send only the delta.
Design
I used a trie. A trie made the hierarchical shape explicit, and its properties made it easier to reason about differences between stored versions.
The immutable nature of the structure simplified much of the logic. Instead of mutating arbitrary branches in place, updates could produce new structure with shared unchanged parts. That made reconciliation easier to reason about and reduced the amount of data that needed to move across the network.
The project also gave me a reason to deepen my Python and Angular knowledge, but the synchronization structure was the main lesson.
What Worked
The biggest win was choosing a data structure that matched the problem. Once the state was represented in a way that made comparison natural, the network protocol became simpler.
The other useful lesson was that visual products still need a strong internal model. A pleasant interface is fragile if the underlying state is hard to trust.
What I Would Change
Today I would document the sync protocol more formally and add property-based tests around reconciliation. Synchronization code is exactly the kind of code that benefits from generated edge cases.
I would also separate the visual experiment from the state synchronization story more explicitly. The latter is the part that aged better.