Skip to main content

Deployment Topology

Status

Active

Date

2026-04-28

Owners

  • Platform Backend

Last Verified Commit

Use git log -- <this file> for current last-touch history; this field is intentionally not pinned to a static hash so it does not become stale after unrelated commits.

Local Stack Source

The canonical local deployment topology is the Compose stack in:

  • servers_v2/docker-compose.yml

The stack is contract-tested by:

  • servers_v2/tests/test_compose_contract.py

Infrastructure Services

ServicePurposeLocal Port
postgresshared PostgreSQL runtime5433
redisshared Redis runtime and stream transport6381
migrateone-shot migration bootstrapnone

Application Services

ServiceLocal PortHealth Mode
gateway8080/health
player_service8010/health
wallet_service8011/health
game_service8012/health
rolling_service8013/health
promotion_service8014/health
agent_service8015/health
admin_service8016/health
recon_service8017/health

Base compose publishes gateway on the host-facing default bind because it is the local player/API entrypoint. Every other published application and infrastructure port is pinned to 127.0.0.1, including admin_service and agent_service; expose those services outside the host only through an external ingress boundary such as VPN/LB/firewall/TLS plus auth, rate limits, and allow-lists. The compose file is a local verification topology, not a full public production network boundary.

Worker Services

WorkerPurposeHealth Mode
wallet_workerwallet outbox publishing, outbox lag gauges, outbox cleanup, orphan authorization sweeper, hourly ledger-vs-balance reconciliationheartbeat file + readiness
rolling_workerwallet-event consumer, outbox, outbox cleanup, expiry, completion retryheartbeat file + loop freshness
promotion_workerwallet-event consumer, settlement scheduler, saga recoveryheartbeat file + scheduler readiness
agent_workeragent outbox publishing, outbox cleanup, coupon wallet saga dispatchheartbeat file
admin_workerscheduled admin jobsheartbeat file + scheduler job health
recon_workerPushbullet/Telegram/recon loopsheartbeat file + loop freshness
player_workerplayer outbox publishing (ENABLE_OUTBOX_POLLER=true); player_service API has it disabled and depends_on: player_worker to guarantee the worker is healthy before trafficheartbeat file

Current Split-Worker Rule

Services with dedicated background work run that work in a standalone worker so APIs can scale independently.

There are currently no exceptions. Compose keeps API-owned process flags off for worker-owned loops (ENABLE_*: "false" on APIs) and enables the matching flags on worker containers. servers_v2/tests/test_compose_contract.py locks that split so API horizontal scaling cannot duplicate settlement, saga, cleanup, scheduler, or stream-consumer loops.

Environment Files

Local stack usage is designed around:

  • servers_v2/.env.compose.example
  • servers_v2/.env.compose.local

Sensitive values are intentionally env-driven and must not be committed into the Compose file.

Multi-Brand Mode

Per ADR-009, every brand runs on the same Compose stack:

  • one postgres, one redis, one set of application services and workers
  • brand identity is resolved per request from the request domain (or, for game callbacks, from the namespaced outbound account); no per-brand process duplication
  • a MULTI_BRAND_ENFORCEMENT env var (off / observe / enforce) controls Gateway's JWT-vs-domain brand mismatch behavior; the repository compose default is now enforce, with observe reserved for explicit soak/rehearsal overrides

Use the local-stack runbook:

  • docs/runbooks/local-docker/local-docker-full-stack.md