--- id: managed-store title: Losing the box does not lose login grants status: open repos: [headquarters, infra] dependsOn: [] exitCriterion: > The api host can be replaced without anybody being signed out, and no durable state lives on its disk. --- # managed-store Decided 2026-08-01, unstarted. Durable server state belongs in an AWS-managed database, not in sqlite on one instance: losing the box must not lose login grants. The api host deploys with sqlite on a persistent volume as a stopgap, and that is the whole of the durability story today. There is one instance, and its disk is what stands between a player and signing in again. ## What moves - [ ] **The swap itself.** DynamoDB fits the key-value shape, and the change is contained behind the atproto `Store` wrapper. sqlite stays as the no-AWS dev mode — the point is that one binary supports both, not that sqlite goes away. - [ ] **The table** (infra). Nothing to write there until headquarters is ready to swap behind the wrapper. - [ ] **The default camo column.** One nullable TEXT column on `account`, carrying which camo lance.blue reaches for. A key that no longer resolves already reads as "no default", so it moves whenever the rest of the table does and needs no migration of its own. See [camo](complete/camo.md). - [ ] **Decide what the matches registry is.** It is described as ephemeral — OAuth sessions plus a live-match registry is the whole of what the api keeps — but [match-lifecycle](match-lifecycle.md) wants retention and paging over it, which is not an ephemeral shape. Settle whether match rows are durable state that moves with the rest, or a cache that a restart is allowed to empty. ## What this unblocks An admin surface. `infra/scripts/matches/killall.sh` writes the sqlite directly, which is only possible because the store is a file on the box the operator can reach. An API that ends a match properly is easier to justify once the store is not that. It is also a precondition for more than one instance of anything, which `proxy-split` will eventually want — though the proxy's own reason to split is deploys dropping live matches, not state. ## Done Nothing closed yet.