Skip to content

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.

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.

See Matchmaking API § Create a backfill request.