Backfill
A running match has open slots: someone disconnected, or it started under-full.
sequenceDiagram
autonumber
participant GS as Game Server
participant GB as Your Backend
participant IM as IVK Match
actor NP as New Player
Note over GS: A player leaves, 2 slots open
GS->>GB: report_open_slots(match_id, 2)
GB->>IM: CreateBackfillRequest(queue_id, match_id,<br/>ruleset_id, slots_requested=2, engine_input)
IM-->>GB: backfill_id
NP->>GB: queue_matchmaking(...)
GB->>IM: CreateTicket(...)
IM->>IM: backfill stage assigns tickets to the request
IM->>GB: outcome: backfill.created<br/>{ request, assigned_tickets }
GB-->>NP: game_found { address, port }
NP->>GS: connect
Note over GS: Match is full again
GS->>GB: report_full(match_id)
GB->>IM: CancelBackfillRequests(queue_id, [backfill_id])
Note that the game server reports to your backend, not to IVK Match. The boundary is the same as everywhere else: only your backend calls the matchmaker.
What to know
Section titled “What to know”Re-posting is safe, and easier than tracking state. A new request for the same match_id
replaces the previous one, so a running server can re-post its current open-slot count on a
timer instead of tracking whether it already has a request outstanding and by how much it has
changed.
ruleset_id is required whenever the queue has more than one ruleset. There is no sensible
default, so a missing one is rejected rather than guessed. Omit it only in single-ruleset queues.
The outcome is self-describing. Backfill.request echoes your original request in full, so you
do not need a side lookup to work out which match the new players belong to.
Cancel when the match fills or ends. Otherwise the request sits until
backfill_requests.expiration_ttl_secs elapses and emits backfill.expired. Nothing breaks, but
the matchmaker spends that time trying to fill a match that no longer needs players.