-- Retention support. Three tables grow without bound today: -- -- idempotency_keys -- the client heartbeats every 10s and mints a fresh key -- each time, so at 10,000 queued players this alone adds roughly 60,000 -- rows per minute, forever. -- outbox -- published rows are never purged. -- sessions -- expired and revoked rows are never purged. -- -- The maintenance role performed lifecycle reconciliation only, so storage, -- index size, vacuum pressure, backup size and recovery time all grew without -- limit on a service meant to scale horizontally. -- -- These indexes exist to make the deletion predicates cheap; without them each -- purge pass would sequentially scan the very tables it is trying to bound. CREATE INDEX IF NOT EXISTS idempotency_keys_created_at ON idempotency_keys (created_at); CREATE INDEX IF NOT EXISTS outbox_published_at ON outbox (published_at) WHERE published_at IS NOT NULL; CREATE INDEX IF NOT EXISTS sessions_expires_at ON sessions (expires_at);