When Provisioning Fails
The match is real but no server can be obtained for it. Those players have already left the pool, so doing nothing strands them. The integration returns them to the pool rather than sending them back to the menu.
sequenceDiagram
autonumber
participant IM as IVK Match
participant GB as Game Backend
participant OR as Orchestrator
actor P as Players
IM->>GB: outcome: match.created { match_id, tickets, host }
GB->>OR: CreateGameServer(host = host.preferred)
OR-->>GB: error, capacity exhausted
loop for each host in host.acceptable
GB->>OR: CreateGameServer(host)
OR-->>GB: error
end
Note over GB: No server available on any acceptable host
GB->>IM: ReactivateTickets(queue_id, ticket_ids)
IM-->>GB: failed_ticket_ids: []
Note over IM: Tickets are back in the pool,<br/>keeping their original created_at
GB-->>P: still searching (no error shown)
This relies on three things.
host.acceptable is a ready-made fallback list
Section titled “host.acceptable is a ready-made fallback list”Every host in engine_output.host.acceptable is tolerable to every ticket in the match, not just
some of them. Walk it before declaring provisioning failed. A capacity failure in one region is
common; a capacity failure in every region a match can tolerate is rare.
ReactivateTickets preserves queue position
Section titled “ReactivateTickets preserves queue position”Reactivated tickets keep their original created_at, so a player who already waited 90 seconds does
not go to the back of the line. As far as the player is concerned nothing happened. They were never
told a match was found, and they are still searching.
That is why the player-facing message here is “still searching” rather than an error. The failure is absorbed by the backend.
terminal_retention_ttl_secs is the compensation window
Section titled “terminal_retention_ttl_secs is the compensation window”A resolved ticket can only be reactivated while it is still retained. Any ticket returned in
failed_ticket_ids was already evicted and needs a fresh CreateTicket instead.
Set pool.tickets.terminal_retention_ttl_secs above the orchestrator’s worst-case provisioning
timeout plus the time it takes to walk the fallback list. The default of 300 s suits most
setups; use 3600 s where provisioning can be slow.
A non-empty failed_ticket_ids indicates that the window is too short for the provisioning path,
rather than a one-off.
Do not silently drop the match
Section titled “Do not silently drop the match”A match.created that is neither honoured nor compensated for leaves every other ticket in that
match waiting. If the outcome handler crashes mid-provisioning the outcome
will be redelivered, since delivery is at-least-once, so an idempotent handler keyed on Match.id
recovers on its own.