Realtime card & casino platform — server topology

System Architecture

Seven-layer server stack on GCP. Clients hold a JWT and speak one binary socket to the User Controller; every service behind it talks raw TCP. Target 64 CCU per room shard, horizontally packed into containers by the Agent Server.
CLOUD
GCP + Cloud LB
STORE
MariaDB
CACHE
Redis (single cluster)
TARGET CCU
{{ ccu }} / room
VIEW 01

Overview topology

every edge labeled protocol · port · payload
CLIENT
Game Client
Web / mobile. Holds JWT in memory, one persistent socket, auto-reconnect with backoff.
EDGE / STATIC
Cloud CDN
Client bundle, card art, sprite atlases, remote config JSON. Cache-busted by build hash.
HTTPS 443 · REST + WSS upgrade
HTTPS 443 · cached assets
GCP Cloud Load Balancer
L7 for auth (HTTP) · L4 pass-through for game sockets · TLS termination · health checks · session affinity by client IP
HTTP/JSON · /login /refresh /verify
TCP 7000 / WSS · length-prefixed binary + JWT handshake
LAYER 01
stateless · N replicas
Authenticator
First layer a user meets. Verifies credentials, issues the JWT that carries the session everywhere downstream.
  • · Credential / OAuth / guest-device login
  • · JWT sign + rotate (access 15 m, refresh 30 d)
  • · Public key set for downstream verification
  • · Ban & device-block check, login rate limit
LAYER 02
stateful · holds the socket
User Controller
The only layer that touches a client socket. Proxies every downstream service; owns framing, buffering, session lifetime. See View 02.
  • · Socket + WebSocket accept, JWT handshake
  • · Packet pack / unpack, partial-frame buffer
  • · Silent JWT refresh, reconnect resume
  • · Disconnect grace timer → destroy session
RAW TCP · internal mesh · routed by session id + service id
LAYER 03
Lobby
Matchmaking and routing. Decides which room a user lands in, and asks the Agent for capacity when there is none.
  • · Matchmaking queue (stake / mode / skill)
  • · Room routing + seat reservation
  • · Game event & server notice broadcast
  • · Capacity request → Agent Server
LAYER 04 + 05
{{ ccu }} CCU / shard
Game Room extends Room Core
Room Core owns the lifecycle, the connected-user list and all infrastructure. Game Room subclasses it with card logic. See View 03.
  • · Room cycle start / stop / tick
  • · Connected-user list (no direct sockets)
  • · DB, cache and internal-connection managers
  • · Deal / bet / showdown / settlement (subclass)
LAYER 06
Chat Server
User-to-user chat, delivered through the User Controller like every other service.
  • · Direct, room and global channels
  • · Profanity filter, mute & report
  • · History window in Redis, archive in MariaDB
  • · Fan-out over Redis pub/sub across shards
SHARED DATA PLANE — reached by Authenticator, User Controller, Lobby, Game Room and Chat Server alike
MariaDB
TCP 3306 · pooled
Accounts, wallet, hand history, chat archive, room config. Room Core owns pooling, retry, batch writes and transactions.
Redis — single cluster
TCP 6379 · RESP
Session registry, matchmaking queues, room directory, JWT denylist, presence, pub/sub fan-out between shards.
Observability
Cloud Logging (structured JSON, one stream per container) · Cloud Monitoring (CCU, room count, tick latency, socket errors, buffer depth) · alert policies drive the Agent's scale signals.
LAYER 07 · CONTROL PLANE
Agent Server
Spawns containers, assigns config, drains and reroutes when demand falls. Talks to every layer. See View 04.
CONTROL EDGES — raw TCP 9100, bidirectional
Authenticatorendpoint map · key rotation
User Controllerreroute · drain · session move
Lobbyspawn request · shard table
Game Roomconfig · health · stop-when-empty
Chat Serverchannel rebalance
HTTPS · GCP REST API
GCP Compute / Container API
One image, four roles. Each container runs Lobby + Game Room + Chat + User Controller; the assigned config decides which roles activate.
LEGEND
client / data-path edge
supporting / out-of-band
service you own
managed GCP resource
VIEW 02

Zoom — User Controller

the only socket-owning process
Client socket
TCP or WebSocket, one per user. Bytes arrive in arbitrary chunks.
byte stream in ↔ frames out
Downstream
Lobby · Game Room · Chat · Agent, all over raw TCP.
01 · INGRESS
Accept & handshake
  • · Socket + WebSocket listeners on one port
  • · JWT verified against Authenticator's key set
  • · Session record written to Redis
  • · Handshake rejected → close with reason code
02 · FRAMING
Packet pack / unpack
  • · Length-prefixed header: len · opcode · seq
  • · Per-connection ring buffer holds partial frames
  • · Buffer sliced once a full frame is present
  • · Oversize frame → drop connection, log
03 · SESSION
Token & lifetime
  • · Silent JWT refresh before expiry, in-band
  • · Reconnect resumes the session by session id
  • · Disconnect starts a grace timer (e.g. 60 s)
  • · Timeout → destroy session, notify room
04 · ROUTING
Service proxy
  • · Opcode range → target service
  • · Persistent TCP pool per downstream service
  • · Backpressure: per-session outbound queue
  • · Agent-driven reroute without dropping clients
VIEW 03

Zoom — Room Core & Game Room

inheritance: infrastructure below, game rules above
Room Core Controller
base class · no socket access
Everything a room needs that is not the game itself. All client traffic arrives already unpacked, via the User Controller.
LIFECYCLE
  • · start / stop / pause room cycle
  • · tick scheduler
  • · connected-user list & seats
  • · join / leave / kick
DATABASE MGR
  • · MariaDB connect + pool
  • · auth, reconnect, retry
  • · batch writes
  • · transactions
CACHE MGR
  • · Redis connect / reconnect
  • · pipeline & batch
  • · pub/sub channels
  • · key namespacing per room
INTERNAL CONN
  • · raw TCP to other Room Cores
  • · Lobby link
  • · Agent Server link
  • · heartbeat & health report
EXTENDS
Game Room
subclass · card & casino rules
GAME LOGIC
  • · round state machine
  • · shuffle / deal (server-side RNG)
  • · betting, timers, auto-fold
  • · showdown, payout, rake
GAME DATA
  • · own MariaDB tables: hand history, ledger
  • · own Redis keys: table snapshot, timers
  • · replay log for dispute review
  • · inherits the core's pooling & retry
Traffic in and out of a room
User ControllerTCP · player action →Game Room
Game RoomTCP · state delta →User Controller → clients
LobbyTCP · seat reservation →Game Room
Game RoomTCP · room census →Agent Server
Game Roompub/sub · cross-shard event ↔other Room Cores
Why sockets stop at the User Controller
A room never learns whether a player is on TCP or WebSocket, whether their bytes arrived whole, or whether their token is about to expire. It receives clean typed messages and emits state. That is what lets the Agent move a session between containers, and what keeps the game loop free of I/O stalls at {{ ccu }} CCU.
VIEW 04

Zoom — Agent Server & deployment

logical layers vs. physical containers
Agent Server responsibilities
Spawn
Calls the GCP container API to start a new instance from the single platform image, then assigns config: which roles activate, ports, shard id, room templates.
Register
Writes the new endpoint into the Redis shard directory and pushes it to Authenticator, User Controllers and Lobbies so new logins can be routed there.
Consolidate
On low demand, marks thin containers as draining — no new routes — and asks Lobby to place their remaining players on fuller shards at the next round boundary.
Reap
Once a container reports zero connected users and zero live rooms, the Agent stops it and releases the GCP resources.
PHYSICAL VIEW — one image, N containers, roles toggled by config
Container 01ACTIVE
User Controller
Lobby
Game Room — off
Chat — off
Container 02ACTIVE
User Controller
Lobby — off
Game Room ×8
Chat
Container 03DRAINING
User Controller
Lobby — off
Game Room ×1
Chat — off
No new routes. Players move at the next round boundary, then the Agent stops it.
Scale signals
Scale up when free seats across live rooms fall below one room's worth, or a Lobby queue waits past its SLA. Scale down when a container holds under a quarter of its seats for a sustained window. Both signals come from Cloud Monitoring plus the room census each Room Core reports on its Agent link.
VIEW 05

Sequence flows

FLOW ALogin & session
1 Client → LB → Authenticator: credentials over HTTPS
2 Authenticator checks MariaDB, signs JWT, caches session in Redis
3 JWT + User Controller endpoint returned to client
4 Client opens socket, sends JWT in the handshake frame
5 User Controller verifies, registers session, replies READY
FLOW BMatchmaking → room join
1 Client sends FIND_MATCH; UC proxies it to Lobby over TCP
2 Lobby queues by stake and mode in Redis
3 No free seat? Lobby asks Agent to spawn a room shard
4 Lobby reserves a seat on the chosen Game Room
5 UC re-binds the session to that room; ROOM_STATE pushed to client
FLOW CDisconnect → reconnect
1 Socket drops. UC keeps the session, starts the grace timer
2 Room marks the seat AWAY; auto-fold / auto-stand takes over
3 Client reconnects with the same JWT and session id
4 UC re-attaches the socket, replays missed frames from the buffer
5 Timer expires instead? Session destroyed, seat released, chips settled
FLOW DScale up · drain · reroute
1 Monitoring + room census cross the scale-up threshold
2 Agent calls the GCP API, starts a container, assigns its role config
3 Endpoint published to Redis, Authenticator and every Lobby / UC
4 Demand falls: Agent marks a thin container DRAINING
5 Players rerouted at a round boundary; empty container stopped
VIEW 06

Connection matrix

↔ bidirectional · → one-way
From Dir To Protocol Payload
ClientAuthenticatorHTTPS 443 / JSONLogin, refresh; returns JWT + endpoint
ClientUser ControllerTCP 7000 / WSSLength-prefixed binary frames, JWT handshake
ClientCloud CDNHTTPS 443Bundle, art, remote config
User ControllerLobbyraw TCP 9001Matchmaking, routing, notices
User ControllerGame Roomraw TCP 9002Player actions in, state deltas out
User ControllerChat Serverraw TCP 9003Messages, channel join/leave
User ControllerAgent Serverraw TCP 9100Load report, reroute & drain orders
User ControllerAuthenticatorHTTP / JWKSKey set fetch, token refresh on behalf of client
Agent ServerLobbyraw TCP 9100Spawn requests, shard table updates
Agent ServerGame Roomraw TCP 9100Config assign, census, stop-when-empty
Agent ServerChat Serverraw TCP 9100Channel rebalance, health
Agent ServerAuthenticatorraw TCP 9100Endpoint map so new logins route correctly
Agent ServerGCP APIHTTPS / RESTCreate, inspect and stop containers
Room CoreRoom Coreraw TCP 9200Cross-room events, player handover
All servicesMariaDBTCP 3306, pooledBatched writes and transactions via Room Core's DB manager
All servicesRedis clusterTCP 6379, RESPSessions, queues, directory, pub/sub
All servicesCloud Logging / Monitoringagent / HTTPSStructured logs and metrics; feeds scale signals