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 Game 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])

The game server reports to the game backend, not to IVK Match. The boundary is the same as everywhere else: only the game backend calls the matchmaker.

Re-posting is safe and avoids 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 the original request in full, so no separate lookup is needed to determine 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. This causes no errors, but the matchmaker spends that time trying to fill a match that no longer needs players.

See Matchmaking API § Create a backfill request.