executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
scaling-architectureExpert game server scaling — zone sharding, stateless services, state persistence, region/edge routing, observability and capacity/autoscaling orchestration.
Independent GitHub snapshot · Automated classification · Original documentation governs
From "hundreds playing" to "a million in a weekend": how the server fleet grows without breaking determinism, latency or cost. Skill covers zone/sharding, stateless matchmaking + stateful game pods, persistence, region/edge, observability and capacity/autoscaling.
Tier 1: one game server process + one lobby = 10–200 players
Tier 2: many per-region pods; lobby → matchmaker → pod (stateful), stateless elsewhere
Tier 3: zone-sharded (an open world is units of zones), state in DB, edge relay
The rule: stateful = the game pod only; everything else stateless + horizontally scalable.
| Service | State? | Scale |
|---|---|---|
| login / auth | token-cache only | stateless, autoscale |
| matchmaker / queue | KV session state | stateless, replica |
| lobby | KV per lobby | stateless, replica |
| game pod (sim + authoritative) | in-memory world | stateful, region pods |
| anti-cheat ledger | append-only store | stateless readers |
Stateless services scale by adding replicas (a load balancer + key reconciliation). The game pod can't split mid-match — the world is one authority. Match size and zones bound it.
A huge world is divided into zones (usually map regions, ~200–1000 players each):
world = zone_A (pod A) | zone_B (pod B) | ...
zone boundary: players crossing migrate (state transfer + connection handoff)
Each zone runs : authoritative sim + interest management (the IM skill) + a boundary service that exchanges the edge band (entities within N m of the boundary) so players see across seamlessly.
Migration protocol:
detect crossing → freeze at zone, hand serialized entity+connections
→ zone B takes over → client reconnects to zone B pod (token re-issue)
Use interest gating to keep the handshake small (only edge entities travel, not the world).
regions-and-ping).client → edge relay (region-local) → game pod
| Path | Purpose | Cost |
|---|---|---|
| client → relay → pod | gameplay traffic | region-local, low |
| pod → relay → client | snapshots (interest-gated) | proportional to interest |
Keep the relay stateless (it forwards, doesn't decode) — a fleet of relays autoscale like any stateless tier.
// end of match: worker flushes:
SaveProgress(playerId, {mmrDelta, unlocks, inventory})
// idempotent, versioned (optimistic lock per player)
Every service emits red metrics: requests/s, latency, errors, queue depth. Adoption:
| Layer | Tool shape |
|---|---|
| logs | structured JSON, sampled at 1% (heavy paths) |
| metrics | counters + histograms (p50/p95/p99) per service |
| traces | distributed spans: matchmaker→lobby→pod→relay |
| profilers | tick-time histograms per pod (§ tick-loop) |
SLOs (examples):
capacity planner:
DAU → ccu curve → avg concurrent matches → pods(region)
+ headroom 20% + burst pod-provision latency scaled in
Scaling tempts you to split within a match (sub-sim). That breaks determinism (two pods disagree → desync). Never split a match's sim. Split matches (more pods) and (for open worlds) split the world into zones — but a single match = a single pod's sim, forever.
references/zone-and-shard.md — zone partition, boundary migration, edge-band exchange, region-capacityreferences/stateless-services.md — stateless design, idempotency, replica scaling, LB affinityreferences/state-and-persistence.md — golden-state DB, write-behind, optimistic concurrency, durabilityreferences/region-and-edge.md — region routing, edge relays, bandwidth throttling, jitter absorbreferences/observability.md — metrics, traces, logs, SLOs, dashboards, cost of telemetryreferences/capacity-and-autoscaling.md — capacity math, predictive prewarm, autoscale signals, pods