Matchmaking

Ticket lifecycle

How matchmaking sessions, heartbeats, cancellation, and match delivery work, from ticket creation to a terminal result.

A ticket represents one party’s search. A Roblox SDK session manages that ticket from local creation through a terminal result. Start a new session for a new search.

Session states

State What it means Terminal
pending The session exists locally, but creation has not been confirmed. No
matching The service accepted the ticket and the search is active. No
canceling Cancellation was requested; a match may still win. No
matched A valid match is retained in session.Match. Yes
canceled An unsent search was discarded, or cancellation/removal was confirmed. Yes
failed The search ended with a reason in session.Error. Yes

TicketId is assigned before the first request. Its presence does not mean the service accepted the ticket. Read session.State for the initial value; there is no initial StateChanged("pending") event.

Heartbeats and retention

While sessions are live, the SDK batches outstanding work into requests of at most 100 actions. Its default heartbeat interval is 5 seconds. The supervisor stops when no unfinished sessions remain and starts again when you create another session.

A waiting ticket expires 5 minutes after creation or its last successful confirmation. Keep confirming while searching. A published match and its member tickets remain available for 10 minutes after publication.

Confirming or canceling a matched ticket returns the match without extending this fixed retention window. After expiry, the API returns not_found.

Match delivery

On a valid match, the SDK:

  1. Stores the match in session.Match and sets the state to matched.
  2. Fires session.Matched(match).
  3. Fires terminal session.StateChanged("matched").
  4. Disconnects the session’s signals.

Event callbacks may yield; the SDK does not wait for one callback to finish before emitting the next event. Connect listeners immediately after CreateSession and use retained properties when inspecting a session later.

No acknowledgement is required or supported. A terminal matched session sends no further requests. If a handler errors, the SDK does not replay the event; your game can retry its handoff using the retained match.

The retained outcome lives as long as your game retains the session. It is not durable storage and does not replace your game’s handoff recovery strategy.

Cancellation races

session:Cancel() can be called repeatedly. Before network submission begins, it finishes the session locally without creating a ticket. After submission begins, it immediately changes the local state to canceling and schedules cancellation on the heartbeat.

The service checks cancellation against the current ticket state. If a match has already been published, cancellation returns the match. Keep the session registered and keep processing Matched until a terminal outcome.

The raw API’s canceling response means the service accepted cancellation; the SDK presents that outcome as terminal canceled. Do not confuse the raw API state with the SDK’s local, nonterminal canceling state.

Uncertain creation

The SDK generates a ticket GUID before submission. If a create response is lost or malformed, it confirms that known ID on later heartbeats instead of blindly creating another ticket.

If reconciliation cannot find the ticket, the session fails with creation_unresolved. This does not prove that the original request never completed: a slow original request could still finish later. Do not automatically launch a replacement search without accounting for potentially outstanding work.

Party changes and shutdown

Options are copied at creation. Changing the original players, metadata, or rules does not update a live ticket. Cancel the existing session and wait for the terminal outcome before starting a changed search.

Your game owns party registries, Players.PlayerRemoving, and prevention of overlapping sessions. The SDK does not deduplicate separate sessions or clients by player ID.

client:Destroy() fails active sessions with client_destroyed and stops new requests. An in-flight request cannot be revoked; remote tickets may remain matchable until cancellation or expiry. Use destruction for shutdown or intentional abandonment, and cancellation for normal queue exits.