Tangible Distributed Systems Simulator
Table of Contents

(image is a screenshot of https://github.com/pshenok/server-survival, to be replaced with CAD design assignment output)
Motivation#
I build distributed systems at work, and I often crave more tangible visualizations of the systems that I build that I can touch and feel. I’ve played around with UI-based visualizations Such as animated sequence diagrams and state diagrams in the past and gotten some results that I like. I’d love to take that further By exploring physical representations of web system design components.
Description#
Physical objects for understanding distributed systems concepts and patterns. I want to create a tangible simulator environment where physical blocks representing:
- compute nodes
- storage nodes
- network connections
work together to demonstrate distributed systems concepts. Each node contains microcontrollers with displays showing live metrics, connected by illuminated wires that visualize data flow step-by-step.
In addition, the blocks are twins for components in a digital web UI such that some parameters can be bidirectionally manipulated between the digital and physical representation
Why#
Distributed systems are the backbone of modern cloud infrastructure, but their emergent properties are difficult to understand without significant experience. Distributed systems are design to be fault-tolerant (i.e. what happens when one component stops working?) and scalable (i.e. system can seamlessly incorporate addition of new resources with increasing load).
Some example design patterns include:
- circuit breakers to shed load when the service can’t handle it
- autoscaling servers on increasing load, while stateful components like databases must be replicated with other concerns
- consensus and leader election between nodes in case one of them fails
- network partitions causing some components to be inaccessible
The high-level picture of a live system interaction is not clear simply by looking at code. Labeled diagrams are often used, are quite good tools for the real-time control flow visualization.
What if we could:
- physically hold a database replica?
- watch data flow through glowing wires?
- tip over a node to simulate a crash and see if the system recovers on its own?
Inspiration#
This project builds on research in tangible user interfaces and data physicalization:
| Project | Contribution |
|---|---|
| IP Network Design Workbench (MIT Media Lab, 2003) | Physical pucks on sensing table for network topology manipulation |
| Raft Visualization (thesecretlivesofdata.com) | Canonical digital visualization for consensus algorithms |
Scratch Pad (WIP, ignore)#
Diagram#
┌─────────────────────────────────────────────────────────────┐
│ DIGITAL TWIN (Web UI) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Topology │ │ Time-step │ │ Distributed Trace │ │
│ │ View │ │ Controller │ │ (Jaeger-style) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
▲
│ WebSocket
▼
┌─────────────────────────────────────────────────────────────┐
│ ORCHESTRATOR (Raspberry Pi 4) │
│ • Simulation engine (controls timing, injects requests) │
│ • Trace collector │
│ • Network coordinator │
│ • REST API for UI │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ I2C Bus │ UART │ ESP-NOW
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ COMPUTE │ │ STORAGE │ │ NETWORK │
│ NODE │───│ NODE │───│ NODE │
└───────────┘ └───────────┘ └───────────┘
Node Types#
Compute Nodes (Material: Metal/Blue)#
Purpose: Load balancers, application servers, workers, logic executors
Display Views#
Golden Signals View
┌────────────────────┐
│ ▓▓▓▓▓░░░ LAT 45ms │
│ ▓▓▓░░░░░ RPS 120 │
│ ▓░░░░░░░ ERR 2.1% │
│ ▓▓▓▓▓▓░░ SAT 78% │
└────────────────────┘
Connection View
┌────────────────────┐
│ → DB-Primary │
│ → Cache-01 │
│ ← LB-01 │
│ ↔ Worker-02 │
└────────────────────┘
Live Requests View
┌────────────────────┐
│ GET /api/users │
│ ├─► db.query() │
│ └─► cache.get() │
│ 23ms ✓ │
└────────────────────┘
Storage Nodes (Material: Wood/Green)#
Purpose: Databases, caches, key-value stores, file storage
Storage-Specific Displays#
Database Mode
┌────────────────────┐
│ PostgreSQL [PRIMARY]│
│ QPS: 1.2k Conn: 45│
│ Rep Lag: 12ms │
│ ████████░░ 80% full│
└────────────────────┘
Cache Mode
┌────────────────────┐
│ Redis [REPLICA 2/3]│
│ Hit: 94% Mem: 2.1G│
│ Keys: 45.2k │
│ Evictions: 23/min │
└────────────────────┘
Replication View
┌────────────────────┐
│ ┌───┐ │
│ │ P │ ──► R1 ✓ │
│ └───┘ ──► R2 ✓ │
│ ──► R3 ⚠ │
│ lag: 0, 0, 45ms│
└────────────────────┘
Network Nodes (Material: Clear Acrylic/Orange)#
Purpose: Physical representation of network connections
Packet Visualization#
| Color | Meaning |
|---|---|
| 🔵 Blue | Read request |
| 🟢 Green | Write request |
| 🟡 Yellow | Heartbeat / health check |
| 🔴 Red | Error / timeout |
| ⚪ White | Replication traffic |
Packets appear as moving light pulses traveling through the wire, making data flow physically visible.
Time-Step Exploration#
A powerful feature for learning is step-by-step execution. Rather than watching requests fly by in real-time, users can pause the simulation and advance one step at a time, watching each operation complete sequentially.
Physical Feedback During Steps#
Example: Request Flow Visualization#
Step 1: Request arrives at Load Balancer
┌──────┐ ┌──────┐ ┌──────┐
│ LB │ ← ━━━━━ │ │ │ │
│ ●●●● │ req │ Srv │ │ DB │
└──────┘ └──────┘ └──────┘
↑ ACTIVE dim dim
Step 2: LB routes to Server
┌──────┐ ┌──────┐ ┌──────┐
│ LB │ ━━━━━ → │ Srv │ │ DB │
│ ○○○○ │ req │ ●●●● │ │ │
└──────┘ └──────┘ └──────┘
done ↑ ACTIVE dim
Step 3: Server queries Database
┌──────┐ ┌──────┐ ┌──────┐
│ LB │ │ Srv │ ━━━━━ → │ DB │
│ │ │ ◐◐◐◐ │ query │ ●●●● │
└──────┘ └──────┘ └──────┘
done waiting ↑ ACTIVE
Digital Twin Interface#
The web-based companion interface provides:
Simulation Controls#
┌─────────────────────────────────────────────────────────────┐
│ ◀◀ ◀ [▶ PLAY] ▶ ▶▶ Speed: [1x ▼] │
│ │
│ Step: 47/312 Time: 00:00:12.450 │
│ ═══════════════●════════════════════════════════ │
└─────────────────────────────────────────────────────────────┘
Distributed Trace View (Jaeger-style)#
┌─────────────────────────────────────────────────────────────────┐
│ Trace: req-7f3a2b Duration: 127ms Spans: 5 │
├─────────────────────────────────────────────────────────────────┤
│ LB-01 ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 3ms │
│ Worker-02 ██████████████████████████████████████ 112ms │
│ ├─ db.query ████████████████████████░░░░░░░░░ 89ms │
│ ├─ cache.get ████░ 8ms │
│ └─ transform ██ 4ms │
│ DB-Primary ████████████████████████░░░░░░░░░ 89ms │
│ Cache-01 ████░ 8ms │
│ ────────────────────────────────────────────────────────────── │
│ 0ms 25ms 50ms 75ms 100ms 127ms │
└─────────────────────────────────────────────────────────────────┘