Integration Flow
This page covers the happy path. The game backend submits a ticket, IVK Match forms a match and pushes it to the backend, and the backend provisions a server and tells the player where to connect.
Throughout the flow, IVK Match never communicates with players, and players never communicate with IVK Match. The game backend always sits in between. That keeps authentication, anti-cheat, skill lookup, and rate limiting where they already live.
The diagrams name operations by their gRPC name (CreateTicket, CancelTicket, and so on). Each is
equally available as an HTTP/JSON call and the flows are identical either way; see
Matchmaking API § Two transports, one API.
The sequence
Section titled “The sequence”sequenceDiagram
autonumber
actor P as Player
participant GB as Game Backend
participant IM as IVK Match
participant OR as Orchestrator
participant GS as Game Server
P->>GB: queue_matchmaking(playlist, party)
Note over GB: Look up MMR, measure/read latencies,<br/>resolve platform + crossplay prefs
GB->>GB: ticket_id = uuid4()
GB->>IM: CreateTicket(ticket_id, queue_id, ruleset_ids,<br/>engine_input, metadata)
IM-->>GB: ticket_id (ack, ticket is in the pool)
GB-->>P: queued (ticket_id)
Note over IM: Every tick (default 1s) the engine improves<br/>the matches it is assembling from the pool
IM->>IM: match formed, tickets leave the pool
IM->>GB: outcome: match.created<br/>{ match_id, tickets[metadata], engine_output }
Note over GB: Decode engine_output →<br/>teams + host.preferred
GB->>OR: CreateGameServer(host=preferred, match_id, players)
OR->>GS: start
GS-->>OR: ready (address, port)
OR-->>GB: server { address, port }
GB->>GB: persist session(match_id → server, players)
GB-->>P: game_found { match_id, address, port, team }
P->>GS: connect
Step notes
Section titled “Step notes”Step 2: enrich before submitting. IVK Match has no knowledge of the players. Everything the
engine needs goes in engine_input: player IDs, MMR, per-host latencies, and the attributes named by
the queue’s attr_filter. Anything the backend needs back goes in metadata.
Step 4: the backend owns the ticket ID. Generate a UUID before calling. If the call times out, retry with the same ID; it cannot create a duplicate.
Step 5: the ack is not a match. CreateTicket returns when the ticket is durably pooled. Show
the player a queue state, not a match.
Step 8: the outcome is the match. By the time match.created arrives, those tickets have
already left the pool. The match is a commitment: those players are no longer matchmaking. If it
cannot be honoured, the backend must compensate actively. See
When provisioning fails.
Step 9: host.preferred drives placement. The latency map keys supplied in engine_input
come back as engine_output.host.preferred, with every mutually-acceptable alternative in
host.acceptable. If those keys are the provisioning layer’s own region or pool identifiers, this
step is a direct pass-through with no translation layer.
Step 10: provisioning belongs to the game backend. The orchestrator API, its authentication, and its retry policy all stay on the integration side.
Step 13: correlate via match_id. Match.id is a UUID and the natural session key. It is also
the value a game server will later need for backfill requests.
Where the time goes
Section titled “Where the time goes”| Phase | Typical | Driven by |
|---|---|---|
CreateTicket round trip | single-digit ms | Network |
| Waiting in queue | seconds to minutes | Population, wait_time, ruleset strictness |
| Match formed → outcome delivered | tens of ms | Sink; webhook adds one HTTP round trip |
| Server provisioning | seconds | Orchestrator; usually the dominant term after queue wait |
| Notify player | ms | The game’s own push channel |
Queue wait and server provisioning dominate. At tick_rate_secs: 1 the engine contributes at most
one second of scheduling latency.
Everything that is not the happy path
Section titled “Everything that is not the happy path”Each of these cases needs handling before launch:
| Case | Guide |
|---|---|
| The player backs out, and races a match being formed | Cancel a search |
| A match is real but no server can be had | When provisioning fails |
| Nobody was found, or the queue changed under a player | Timeouts and removals |
| A running match has open slots | Backfill |
Every state a ticket can be in is in the ticket lifecycle reference. Before launch, see the production checklist.