Playground · research instrument
Privacy-firstEdge DB Sync Lab
Place a primary and read replicas at real Fly.io regions, then fire transactions from anywhere on Earth. Reads return from the nearest replica in one short hop; writes animate their forward to the primary — the LiteFS/SQLite edge pattern, with all latency math disclosed.
Independent research instrument — not claimed as MakerPortal shipped product code. Methods, equations, assumptions, and limitations are disclosed so you can inspect what the page does and does not establish.
Read the field note →Replication simulator
Topology & traffic
Click a region marker to apply the selected action; click open ocean/land to fire a client transaction from that point.
World map — real Fly.io region locations · Natural Earth geometry, self-hosted
loading land…● primary · ● replica · ● unused region · ● read path · ● write forward
Read vs write latency — last 40 transactions (model)
Anatomy: one writer, many readers
- 01
SQLite stays SQLite. LiteFS is a FUSE layer under the database file. The app on every node opens
app.dbnormally — no client library, no wire protocol, reads are local file I/O with microsecond latency. - 02
Primary election. A Consul lease guarantees exactly one writer. When the primary's lease lapses (deploy, crash), a candidate replica promotes — the
.primaryfile on each replica always names the current one. - 03
Page-level replication. Committed transactions ship as LTX page sets in commit order. Replicas apply them atomically — a replica never serves a torn transaction, only a slightly older complete one.
- 04
Write forwarding. A write landing on a replica answers with
fly-replay: instance=<primary>; the router replays the request in the primary region. That is the long rose-colored arc in the simulation — the price of the single-writer guarantee.
Single-writer, many-reader. Every guarantee and every cost in this lab follows from that one arrow direction.
Gear behind this build
Home edge lab · 6 picks
SBCs · storage6
$134.99SBCVilros Raspberry Pi 4 4GB Basic Starter Kit with Fan-Cooled Heavy-Duty Aluminum Alloy Case
4GB Pi 4 kit with case/fan — the compute base for BLExAR's LiDAR, thermal, GPS, and audio-array builds.
$16.75StorageSanDisk Ultra SDSQUNS-016G-GN3MN 16GB 80MB/s UHS-I Class 10 microSDHC Card
Storage card used in BLExAR's solar-panel data-logging build.
$269.99StorageSANDISK 1TB Extreme Portable SSD (New Model) - up to 2000MB/s Transfer speeds, USB Type-C connectivity, Reliable Durability - Black - SDSSDE70-1T00-G25
Portable SSD used for studio project storage and backups.
$169.99SBCiRasptek Basic Starter Kit for Raspberry Pi 5 — 4GB RAM, 27W PD PSU, Active Cooler
Pi 5 4GB board — Amazon verified ASIN B0CK3L9WD3. Was SparkFun third-party (no Originals commission); now Amazon affiliate (engineersport-20) for proper tracking.
$259.95SBCCanaKit Raspberry Pi 5 Starter Kit PRO — Turbine Black, 8GB RAM, 128GB
Flagship Pi 5 8GB board — Amazon verified ASIN B0CK2FCG1K (via DuckDuckGo Amazon search). SparkFun third-party gave no commission; now Amazon affiliate.
$38.99AccessoryUSB C Docking Station Dual DisplayPort, 8 in 1 USB Hub with 2 DP, HDMI, VGA, USB C 2.0, A 2.0, PD Charging Port, Multi Monitor Adapter for Dell/HP/Lenovo Laptops
Studio desk dock used across all app development work.
Prices shown were retrieved from the Amazon Product Advertising API on 19 July 2026 and are indicative only — the price and availability on Amazon at the time of purchase apply.
Prices shown were checked against the Amazon product listing on 9 August 2026 and are indicative only — the price and availability on Amazon at the time of purchase apply.
More gear across every app: the full Gear list →
Hardware Kit Builder
Two Pis on your LAN make a real LiteFS primary/replica pair — measure actual replication, not a model.
Build this lab
Home edge-replica lab
Two Pis + fast external SSD = a physical two-region LiteFS/SQLite replication lab on your LAN — measure real read-local vs write-forward latency before renting cloud regions.
- $260
- $270
- $135
- $34
Prices shown were retrieved from the Amazon Product Advertising API on 19 July 2026 and are indicative only — the price and availability on Amazon at the time of purchase apply.
Prices shown were checked against the Amazon product listing on 9 August 2026 and are indicative only — the price and availability on Amazon at the time of purchase apply.
Estimated total
$530
Prices from Amazon catalog cache · may change
The latency model, in full
Great-circle distance
Haversine on a sphere of R = 6371 km. Numerically stable for the short hops (client → local replica) where the naive arccos formula loses precision.
Fiber propagation
Light in silica travels at c/1.468 ≈ 204,000 km/s — the single hardest constraint in distributed systems. k accounts for cables not following great circles. Both constants are stated, not hidden.
Transaction cost
r* = nearest replica to client c, P = primary. Each RTT = 2·t_prop + 1 ms processing. The write's second term is the fly-replay forward — the whole architectural argument in one sum.
What the model deliberately omits
TCP/TLS handshakes (amortized by connection pooling), congestion and jitter, replication lag on the read path (async — a replica may serve slightly stale data at zero latency cost), and fsync time at the primary. Omissions all favor no side: handshakes penalize both paths equally; replication lag is a consistency cost, not a latency one. For measured numbers, deploy the litefs.yml below and run real pings.
Production pattern — write forwarding in ~10 lines
The middleware that turns the simulation into a running system, plus a replica-safe litefs.yml. Fly.io ↗ runs LiteFS as a first-class pattern; the same code works anywhere FUSE does.
// Write-forwarding middleware (Hono/Express-style) — the whole trick.
// Reads hit local SQLite replica; writes replay to the primary region.
import { readFileSync, existsSync } from 'node:fs';
const PRIMARY_FILE = '/litefs/.primary'; // LiteFS writes this on replicas
function primaryRegion(): string | null {
// On the primary this file doesn't exist; on replicas it names the primary.
return existsSync(PRIMARY_FILE)
? readFileSync(PRIMARY_FILE, 'utf8').trim()
: null;
}
export function forwardWrites(req: Request): Response | null {
const isWrite = !['GET', 'HEAD', 'OPTIONS'].includes(req.method);
const primary = primaryRegion();
if (isWrite && primary) {
// Fly's proxy replays the full request in the primary's region.
return new Response(null, {
status: 409,
headers: { 'fly-replay': `instance=${primary}` },
});
}
return null; // handle locally — reads are always local
}
/* litefs.yml (replica-safe defaults):
fuse:
dir: "/litefs"
data:
dir: "/var/lib/litefs"
lease:
type: "consul"
candidate: ${FLY_REGION == PRIMARY_REGION} # only primary region runs candidates
promote: true
proxy:
addr: ":8080"
target: "localhost:8081"
db: "app.db"
passthrough: ["/health"]
*/Export · Soft gate
Export topology + latency matrix
Place primary and read replicas across Fly.io regions. Watch reads hit local replicas while writes forward with speed-of-light fiber latency math.
File · edge-topology-report.json
edge-topology-report.jsonapplication/json+ watermark line on free pathFree download adds a small footer:
/* Export from makerportal.ai — free watermarked build. Unlock …Clean export removes footer. Both are generated fresh from your current sim tuning.
Privacy: email stays in your browser localStorage (mp_export_email_fly-edge-db-lab) + unlock flag (mp_export_unlock_fly-edge-db-lab). If Buttondown username is configured, we also POST to Buttondown (privacy-first mode, no tracking pixels per D-014). See privacy → affiliates & email.
Unlock clean export
Soft gate — no hard paywall, no Clerk. Email stays local unless you explicitly check the newsletter box. Unsubscribe anytime. RSS at /rss.xml.
✓ Lab Pro — clean export on every lab
Your licence unlocks this and every other gated simulator, so there is nothing to enter here. Manage or sign out on the shop page.
✓ Unlocked — clean exports enabled
Stored in mp_export_unlock_fly-edge-db-lab. Clean file omits watermark. Re-lock via browser devtools → localStorage.
Frequently asked questions
Are these real measured pings to Fly.io regions?
No — and the page says so everywhere a number appears. Latencies come from a physics model: great-circle distance, light propagating at c/1.468 in fiber (≈ 204,000 km/s), a 1.5× route-inflation factor for real cable paths, and 1 ms per-hop processing. That model lands within tens of percent of real inter-region RTTs, which is enough to make the architectural point: reads from a local replica are one short round trip; writes pay the full trip to the primary. Your real numbers will differ — deploy and measure.
What is LiteFS actually doing under the hood?
LiteFS is a FUSE filesystem that sits under SQLite. On the primary it intercepts committed transactions at the page level and streams them to replicas as an ordered log (LTX files); replicas apply pages and serve plain read-only SQLite. There is exactly one writer — a lease (via Consul) elects the primary. Nothing about SQLite itself changes; your app opens the same database file.
How do writes from a user in Sydney reach a primary in Virginia?
Write forwarding. The Sydney replica cannot commit, so the app responds with a fly-replay: region=iad header (or proxies internally); Fly's router replays the whole HTTP request in the primary region, the write commits there, and replication streams the new pages back out. The Code section shows the ~10-line middleware that implements this — the simulation animates exactly this path.
When does this architecture stop making sense?
When your write fraction gets large or writes need low latency from every geography (every write pays the trip to one primary), when replicas must never serve stale reads (replication is asynchronous — read-your-writes needs session pinning or waiting on replication position), or when a single write region becomes a compliance problem. The lab makes the first two visible: crank up write traffic and watch the advantage evaporate.
Shareable still
The instrument, captured—not illustrated.
This 16:9 frame is rendered from the real browser instrument above. It is the page's canonical preview for image search, link unfurls, and posts that need to show what the tool actually does.
Download 1280 × 720 JPEG
Continue the experiment