Skip to content

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.

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 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.

PhaseTypicalDriven by
CreateTicket round tripsingle-digit msNetwork
Waiting in queueseconds to minutesPopulation, wait_time, ruleset strictness
Match formed → outcome deliveredtens of msSink; webhook adds one HTTP round trip
Server provisioningsecondsOrchestrator; usually the dominant term after queue wait
Notify playermsThe 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.

Each of these cases needs handling before launch:

CaseGuide
The player backs out, and races a match being formedCancel a search
A match is real but no server can be hadWhen provisioning fails
Nobody was found, or the queue changed under a playerTimeouts and removals
A running match has open slotsBackfill

Every state a ticket can be in is in the ticket lifecycle reference. Before launch, see the production checklist.