# Backfill

> Allow players to join matches that have already started and keep servers full as players leave.

Backfill is a flow that allows players to join a game that has already started.

Backfill can have different goals:

* To start a match faster, without all the required players. In this case, backfill is initiated by Matchmaker when the Matchmaker configuration has the `backfill` property set to `true`.
* To keep a steady number of players in a match even if players are leaving. In this case, the game server initiates the backfill when creating a backfill ticket.

Even if a configuration has the property `backfill` set to `false`, backfill will still work when a backfill ticket is created.

> **Warning:**
>
> Setting minimum players to 1 without backfill enabled will allocate a separate server for every player. When the minimum player count is one, the matchmaker considers a match found as soon as a single player enters the queue. The means each player immediately fulfills their own match and receives a dedicated server allocation. Without backfill, those servers never request additional players, so no two players will ever end up in the same game.
>
> If you want multiple players to share a server, do one of the following:
>
> * Set the minimum player count to the smallest group size you want co-located.
> * Enable backfill so that allocated servers can request additional players after the initial match.

## Optimize matchmaking configuration for backfill use cases

For backfilling, it is not recommended to set the minimum number of players to create a match to one (1). This might
result in the creation of a large number of matches which can prevent backfilling from working efficiently. This is especially true when there is a low number of servers backfilling at the same time.

Instead, the recommended best practice is to set the minimum number of players to a large number, or equal to the maximum number of
players in a match, and to relax that minimum number of player to a lower number after a little while (at least four seconds).

### Example

The following example shows that the first match is created if there are 60 players in the match, and then
after five seconds, the subsequent match is created if at least one player is in the match.

```json
{
  "Name": "60 Players",
  "MatchDefinition": {
    "Teams": [
      {
        "Name": "Team",
        "TeamCount": {
          "Min": 1,
          "Max": 1
        },
        "PlayerCount": {
          "Min": 60,
          "Max": 60,
          "Relaxations": [
            {
              "Type": "RangeControl.ReplaceMin",
              "AgeType": "Oldest",
              "Value": 1,
              "AtSeconds": 5
            }
          ]
        },
        "TeamRules": []
      }
    ],
    "MatchRules": []
  },
  "BackfillEnabled": true
}
```

## Backfill flow

The following diagram shows the backfill flow:

```mermaid
sequenceDiagram
    participant DGS as Dedicated Game Server
    participant PA as Payload Allocation
    participant TP as Token Proxy
    participant MM as Matchmaker
    participant GC as Game Client

    DGS->>PA: GET https://localhost:8086/payload/<allocation_uuid>
    note over PA: Server fetches the payload<br/>allocation information
    PA-->>DGS: Server receives payload with backfill ticket Id

    note over DGS: Server approves the backfill ticket<br/>to add more players to the match
    DGS->>MM: POST /v2/backfill/{BackfillTicketId}/approvals
    note over MM: Matchmaker adds the backfill<br/>ticket to the list of matches available

    GC->>MM: Game Client sends a matchmaking ticket
    note over MM: Matchmaker adds the ticket<br/>to the backfill ticket
    MM-->>GC: Game Client polls every second and<br/>eventually retrieves the assigned ticket

    note over DGS: Server keeps approving the backfill ticket<br/>every second to add more players to the match
    DGS->>MM: POST /v2/backfill/{BackfillTicketId}/approvals
    note over MM: Matchmaker assigns the server<br/>from the backfill to the added ticket
    MM-->>DGS: Returns the updated backfill ticket

    note over DGS: Server gets the updated backfill and realizes<br/>it is now full and deletes the backfill
    DGS->>MM: DELETE /v2/backfill/{BackfillTicketId}
    note over MM: Matchmaker deletes<br/>the backfill
```

1. When the server is allocated, it fetches the allocation payload information and the [matchmaking results](https://services.docs.unity.com/matchmaker/v2/index.html#tag/matchmaking_results_model). The matchmaking results contain the backfill ticket ID that was created by the matchmaker as well as important information needed to create backfill tickets.
2. The server uses a service account token to authenticate the game server to the Matchmaker service. Refer to [Admin authentication](https://services.docs.unity.com/docs/service-account-auth/index.html).
3. The game server approves the backfill ticket every second. This is required to prove to the Matchmaker service that the game server is still running.
4. When a compatible new ticket comes in, the Matchmaker service adds it to an existing backfill ticket.
5. After the ticket is added to a backfill match, the player ticket is assigned to the server the next time the game server approves the backfill ticket.
6. After the match is full, the game server deletes the backfill ticket.

A game server is responsible for keeping a backfill ticket up-to-date. For example, if a player leaves or joins the server outside of Matchmaker, the game server needs to inform the Matchmaker service by updating the backfill ticket.

When a game server needs to backfill players who have left the game and there aren't any backfill tickets, the game server creates a new backfill ticket.

> **Note:**
>
> If a backfill ticket isn't approved regularly by the game server, then the Matchmaker service automatically deletes the ticket. Regular approval ensures that backfill tickets are only valid as long as the game server is running. If a backfill ticket is deleted, either timed out by the Matchmaker service or by the game server, the tickets that were not assigned are put back into the pool of tickets.

## Create a backfill ticket

The following code sample demonstrates how to create a backfill ticket from a game server:

> **Note:**
>
> The CURL samples on this page authenticate with a Service Account token. Refer to [Authentication](./authentication.md#service-account-authentication) to create one.

### Unity SDK

```cs
// Set the Match Properties. These properties can also be found in the Allocation Payload (cf Allocation Payload)

var teams = new List<Team>{
                    new Team( "Red", "9c8e302e-9cf3-4ad6-a005-b2604e6851e3", new List<string>{ "c9e6857b-a810-488f-bacc-08d18d253b0a"  } ),
                    new Team( "Blue", "e2d8f4fd-5db8-4153-bca7-72dfc9b2ac09", new List<string>{ "fe1a52cd-535a-4e34-bd24-d6db489eaa19"  } ),
                };

// Define the Players of the match with their data.
var players = new List<Unity.Services.Matchmaker.Models.Player>
{
   new (
       "c9e6857b-a810-488f-bacc-08d18d253b0a",
       new Dictionary<string, object>
       {
           { "Team", "Red" }
       }),
   new (
       "fe1a52cd-535a-4e34-bd24-d6db489eaa19",
       new Dictionary<string, object>
       {
           { "Team", "Blue" }
       })
};

var matchProperties = new MatchProperties(teams, players);


var backfillTicketProperties = new BackfillTicketProperties(matchProperties);

// Set options for matchmaking
var options = new CreateBackfillTicketOptions("queue", "127.0.0.1:8080", new Dictionary<string, object>(), backfillTicketProperties);


// Create backfill ticket
string ticketId = await MatchmakerService.Instance.CreateBackfillTicketAsync
(options);

// Print the created ticket id
Debug.Log(ticketId);
```

### CURL

```bash CURL
# Transform match properties in a base64 format
matchProperties=$(echo '{
  "matchProperties": {
    "teams": [
      {
        "teamName": "Red Team",
        "teamId": "14f18a3e-921d-4165-90b6-ada353e186ca",
        "playerIDs": [
          "c9e6857b-a810-488f-bacc-08d18d253b0a"
        ]
      },
      {
        "teamName": "Blue Team",
        "teamId": "5aa8ae3b-d5b6-463a-9795-9bc10210dc86",
        "playerIDs": [
          "fe1a52cd-535a-4e34-bd24-d6db489eaa19"
        ]
      }
    ],
    "players": [
      {
        "id": "c9e6857b-a810-488f-bacc-08d18d253b0a",
        "customData": {
          "Team": "Red"
        }
      },
      {
        "id": "fe1a52cd-535a-4e34-bd24-d6db489eaa19",
        "customData": {
          "Team": "Blue"
        }
      }
    ],
    "region": "05083faf-3795-47b8-a0dc-c626089c5ac9",
    "backfillTicketId": "dc156067-d140-4c5e-b7d4-90ec51c8333f"
  }
}' | base64)

# Send create backfill ticket request
curl --location --request POST 'https://matchmaker.services.api.unity.com/v2/backfill' \
--header 'Authorization: Bearer {{SERVICE-ACCOUNT-TOKEN}}' \
--header 'Content-Type: application/json' \
--data-raw '{
  "poolId": "e642781a-558f-4c56-a135-c655331cdeee",
  "connection": "127.0.0.1:8081",
  "properties": {
    "data":  "'+$matchProperties+'"
  }
}'
```

## Update a backfill ticket

Backfill tickets are updated automatically by the `backfillingLoopInterval` so there's no need to manually check for updates. Tickets are automatically updated to reflect current player and team statuses.

If you need to manually force a ticket update, you can use the Matchmaker API. However, this method bypasses the sessions tracking of a match state, so it's only required if you are manually managing backfill.

### Update a backfill ticket with the Matchmaker API

```cs
using Unity.Services.Matchmaker;
using Unity.Services.Matchmaker.Models;

await MatchmakerService.Instance.UpdateBackfillTicketAsync(backfillTicketId, updatedTicket);
```

### CURL

```bash CURL
# Transform match properties in a base64 format
matchProperties=$(echo '{
  "matchProperties": {
    "teams": [
      {
        "teamName": "Red Team",
        "teamId": "14f18a3e-921d-4165-90b6-ada353e186ca",
        "playerIDs": [
          "6ebbc1f9-1c42-479c-b80d-9b6f6aa281f3",
        ]
      },
      {
        "teamName": "Blue Team",
        "teamId": "5aa8ae3b-d5b6-463a-9795-9bc10210dc86",
        "playerIDs": [
          "fe1a52cd-535a-4e34-bd24-d6db489eaa19"
        ]
      }
    ],
    "players": [
      {
        "id": "6ebbc1f9-1c42-479c-b80d-9b6f6aa281f3",
        "customData": {
          "Team": "Red"
        }
      },
      {
        "id": "fe1a52cd-535a-4e34-bd24-d6db489eaa19",
        "customData": {
          "Team": "Blue"
        }
      }
    ],
    "region": "05083faf-3795-47b8-a0dc-c626089c5ac9",
    "backfillTicketId": "dc156067-d140-4c5e-b7d4-90ec51c8333f"
  }
}' | base64)

# Send update backfill ticket request
curl --location --request PUT 'https://matchmaker.services.api.unity.com/v2/backfill/{BackfillTicketId}' \
--header 'Authorization: Bearer {{SERVICE-ACCOUNT-TOKEN}}' \
--header 'Content-Type: application/json' \
--data-raw '{
  "poolId": "e642781a-558f-4c56-a135-c655331cdeee”,
  "connection": "127.0.0.1:8081",
  "properties": {
    "data":  "'+$matchProperties+'"
  }
}'
```

> **Note:**
>
> When a backfill ticket is updated by the game server, all unassigned tickets are released into the pool of tickets.

## Delete a backfill ticket

Delete a backfill ticket when:

* The server doesn’t require new tickets.
* The server is stopping.

The following code sample demonstrates how to delete a backfill ticket:

### Unity SDK

```cs
await MatchmakerService.Instance.DeleteBackfillTicketAsync
("1459800b-d463-4197-a903-f00041fdbf6f");
```

### CURL

```sh
curl --location --request DELETE 'https://matchmaker.services.api.unity.com/v2/backfill/{BackfillTicketId}' \
--header 'Authorization: Bearer {{SERVICE-ACCOUNT-TOKEN}}' \
--header 'Content-Type: application/json'
```
