schmelczer-dev/src/content/posts/life-towers-immutable-tries.md

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
src alt
./_assets/towers.png Life Towers goal tracking interface with tower-like visual structures.
systems
web
tools
true 3 towers Full-stack author
Python
Angular
State synchronization
Multi-device goal and task state shared between clients and a server A working synchronization model built around immutable trie properties recruiter-relevant
label type url
Source source https://github.com/schmelczer/life-towers/
label type url
Demo demo https://towers.schmelczer.dev
type src alt caption
image ./_assets/towers.png Screenshot of a life tracking web interface represented with tower-like visual structures. The visual idea was simple; the useful lesson was the synchronization model behind it.

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.