Integration Flow
This is the whole happy path. Your backend submits a ticket, IVK Match forms a match and pushes it to you, you provision a server and tell the player where to go.
One rule underpins all of it: IVK Match never talks to your players, and your players never talk to IVK Match. Your backend is always in the middle. 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 Your 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 you submit. IVK Match knows nothing about your players. Everything the
engine needs goes in engine_input: player IDs, MMR, per-host latencies, and the attributes your
queue’s attr_filter names. Everything you want back goes in metadata.
Step 4: you own 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 reaches you, those tickets have
already left the pool. That is a commitment: those players are no longer matchmaking. If you cannot
honour it, you have to compensate actively. See
When provisioning fails.
Step 9: host.preferred drives placement. The latency map keys you supplied in engine_input
come back as engine_output.host.preferred, with every mutually-acceptable alternative in
host.acceptable. If those keys are your provisioning layer’s own region or pool identifiers, this
step is a direct pass-through with no translation layer.
Step 10: provisioning is yours. The orchestrator API, its authentication, and its retry policy all stay on your 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 | Your 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 needs handling before you ship:
| 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. When you are ready to ship, work through the production checklist.