--- id: proxy-split title: Deploying the API does not drop every live match status: open repos: [headquarters, infra] dependsOn: [] exitCriterion: > An api deploy happens during a live match and nobody playing notices. --- # proxy-split The proxy works and has worked in production since [match-launch](complete/match-launch.md), which started it early inside the api binary — but that is where it still lives. Every api deploy therefore drops every live match, which means the service can only be deployed when nobody is playing. ## What it needs - [ ] **A second binary sharing a library crate.** The workspace already commits to this shape: `services/api` is `headquarters-api`, and the proxy is `headquarters-proxy` with a shared library crate joining them. - [ ] **A drain-on-deploy story.** This is the actual work. A proxy holding live WebSocket connections cannot be replaced the way a stateless API can, and what "drain" means here has to be decided before the compute is chosen: how long a connection is allowed to outlive a deploy, whether a match survives its proxy going away, and what the player sees if it does not. - [ ] **Compute for it** (infra). Nothing is written yet, and infra is explicitly waiting on the drain story to decide. The priced comparison of options was in infra's `docs/decisions.md`, which was deleted; it needs redoing when the decision is live. ## Related The proxy is the auth boundary for a match: it hands each caller their own `/match/{id}//` and refuses any identity that is not the session's. Moving it is therefore also a security-sensitive change, and `security-review` should see the result. More than one instance of anything also wants [managed-store](managed-store.md) first, though that is not this epic's reason to exist — deploys dropping live matches is. ## Done - [x] **Where the single headquarters-api box lives.** Infra's `modules/api-host`: one Graviton instance, Caddy terminating TLS, deploys by image tag. That decision is done and is not reopened by this — the question here is only where the *proxy* runs.