Home Backend Stack & Server

Backend Stack & Server Implementation


1. Summary

Flatland3’s backend is a Rust workspace with a hybrid protocol: binary streaming for real-time sim, HTTP/JSON for agent-facing ops. Durable state lives in PostgreSQL; hot ephemeral state in Redis. The gateway and region worker run as separate processes connected by an internal wire protocol (FL3W postcard over TCP). QUIC lands in a later phase.

See 22-runtime-architecture-and-implemented-features.html for process diagrams and per-feature status.


2. Rust workspace

flatland3/
├── crates/
│   ├── protocol/           # Wire types, postcard codec, version envelope
│   ├── sim/                # Tick loop, AOI, movement (no I/O)
│   ├── region-worker/      # Owns RegionSim @ 30 Hz
│   ├── gateway/            # Client terminate → region route (QUIC later)
│   └── client-lib/         # Bot + future TUI helpers
├── tools/
│   └── bot-harness/        # `flatland-bot` load harness
├── assets/world/segments/  # Seed + authored segments (YAML)
└── migrations/             # sqlx migrations (Phase 2)

Implemented (Phase 1 spike): protocol, sim, region-worker, gateway, client-lib, bot-harness, starter-plains segment.

Next crates: control-plane, world-build, region-orchestrator.


3. Database strategy

Store Role Examples
PostgreSQL Canonical durable state Accounts, characters, inventory, banks, brokers, cartography, unique items, audit log
Redis / Valkey Ephemeral + coordination Sessions, gateway routing table, rate limits, deploy pub/sub, split/merge locks
Object storage Large blobs Segment terrain layers, schematic bundles, deployment artifacts

Rules:

  • Economy and unique-item mints require ACID — Postgres only.
  • Chunk terrain at runtime is in-memory on region workers, loaded from deployed manifest — not queried per tick.
  • sqlx + migrations; SQLite DSN for local single-process dev.

4. Communication protocols

4.1 Client ↔ gateway (game)

Channel Phase 1 Phase 2+ Format
Session In-process / local QUIC (quinn) Versioned envelope
Tick stream Tokio channel QUIC unreliable stream postcard
Intent channel Tokio channel QUIC reliable sequenced postcard
Bulk snapshot On connect QUIC reliable postcard + zstd

Codec decision (benchmarked): postcard v1 — smaller payloads than bincode for TickDelta, serde-native, fast enough for 100×15 entities @ 30 Hz. Revisit FlatBuffers if encode becomes hot.

cargo bench -p flatland-protocol --bench codec_bench

4.2 Agent / ops APIs

API Protocol Consumers
World build HTTP/JSON flatland-world CLI, agents
Deploy status HTTP/JSON CI, ops dashboards
Control plane admin HTTP/JSON Staff tools

4.3 Internal cluster

Link Protocol
Gateway ↔ region worker gRPC (tonic) or QUIC mesh
Region ↔ control plane gRPC
Orchestrator ↔ workers gRPC + Redis pub/sub

5. Protocol types (v1)

Defined in crates/protocol:

Type Direction Purpose
Hello / Welcome C→S / S→C Session + snapshot
Intent C→S Move, stop (sequenced)
TickDelta S→C AOI-filtered entity states
Snapshot S→C Region enter / reconnect
Envelope<T> Both protocol_version wrapper

6. Simulation parameters (locked for Phase 1)

Parameter Value Ref
Tick rate 30 Hz 01
Chunk size 16 m 01
AOI core radius 32 m 06
AOI horizon 64 m (2× core) 06
Interaction radius 1.5 m 03
Item instance IDs UUID v7 03, 18
Seed segment 64×64 m flat grass assets/world/segments/starter-plains.yaml

7. Performance targets

Metric Target How we measure
Region tick 30 Hz stable flatland-sim-stress p95 / mean Hz; /v1/perf
AOI encode < 1 ms for 100 entities codec_bench
Intent → ack p99 < 20 ms LAN bot harness latency
50 bots / region No tick collapse make stress-bot-50 / flatland-bot --local -n 50 --require-perf
100 bots / region No tick collapse make stress-bot-100

Shared gates: flatland_sim::perf_budget. Designer note: docs/performance.md.


8. Phase 1 commands

# Build everything
./scripts/cargo.sh build --workspace

# Unit tests
./scripts/cargo.sh test --workspace

# Codec benchmark (postcard vs bincode)
./scripts/cargo.sh bench -p flatland-protocol --bench codec_bench

# Sim AOI benchmark (real starter-plains, steady-state tick)
./scripts/cargo.sh bench -p flatland-sim --bench aoi_bench

# In-process loadgen (tick budget gates)
./scripts/cargo.sh run -p flatland-sim-stress -- --players 50 --ticks 300
make stress-sim

# Bot load harness (embedded stack + /v1/perf)
./scripts/cargo.sh run -p flatland-bot-harness -- --local -n 50 -d 15 --require-perf
make stress-bot-50
make stress-dense

---

## 9. Next implementation steps

| Step | Deliverable |
|------|-------------|
| **2a** | QUIC gateway (quinn) — replace in-process channels |
| **2b** | Postgres control plane — account, character, position checkpoint |
| **2c** | Region orchestrator stub — metrics hooks for split |
| **2d** | `flatland` TUI — human play on top of `client-lib` | **done (v0)** |
| **2e** | World-build HTTP service — segment CRUD + validate |

---

## 10. Security notes

- JWT or opaque session in Redis; validated at gateway connect
- Workers reject undeployed segment drafts
- Rate-limit intents per session at gateway

---

*Supersedes open protocol questions in `00-initial-vision.html` §4.3 for codec and DB choices.*