PlanyDocs
API reference

GameRegistryService

api.plany.cloud:443Regional14 methods

Register the games you run and the builds behind them. A game is a node in a tree — Minecraft, then Java Edition, then Forge, then a version — and every setting is inherited down it, so your modpack can sit on top of a Plany-published game without copying anything. Upload a build as an archive or point at one, attach it to a game, and every game server created from that game runs it.

CreateBuild

plany.game.v1.GameRegistryService/CreateBuild

Creates a build.

An UPLOAD build comes back in PENDING_UPLOAD with a signed URL in source.upload.upload_url. Every other source is usable immediately.

Parameters

  • parentstringRequired
  • buildBuildRequired
    Show child attributes
    • display_namestringRequired
    • kindKindRequired

      What the artifacts are: a dedicated server, or a playable client.

      Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

      KIND_SERVERKIND_CLIENT
    • sourceBuildSourceRequired
      Show child attributes
      • uploadUploadSourceOne of source
      • steam_cmdSteamCmdSourceOne of source
      • archiveArchiveSourceOne of source
      • container_imageContainerImageSourceOne of source
      • install_commandsrepeated string

        Commands run after the artifacts are in place, in order.

        The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

    • namestringIdentifier

      accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

      Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

      The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

    • versionstring

      Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

    • operating_systemOperatingSystem

      Operating system the build's artifacts target.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • labelsmap<string, string>
  • build_idstring
  • request_idstring

Returns

Build.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"build": {
"display_name": "My server",
"kind": "KIND_SERVER",
"source": {}
}
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/CreateBuild
Example response
{
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"upload": {
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
},
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

GetBuild

Read
plany.game.v1.GameRegistryService/GetBuild

Parameters

  • namestringRequired

Returns

Build.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "builds/my-build"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/GetBuild
Example response
{
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"upload": {
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
},
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

ListBuilds

Read
plany.game.v1.GameRegistryService/ListBuilds

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring
  • filterstring

    AIP-160 filter, e.g. state = "READY".

  • kindKind

    Return only server builds, or only client builds.

    KIND_SERVERKIND_CLIENT

Returns

ListBuildsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"page_size": 50
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/ListBuilds
Example response
{
"builds": [
{
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}
],
"next_page_token": ""
}

UpdateBuild

plany.game.v1.GameRegistryService/UpdateBuild

Parameters

  • buildBuildRequired
    Show child attributes
    • display_namestringRequired
    • kindKindRequired

      What the artifacts are: a dedicated server, or a playable client.

      Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

      KIND_SERVERKIND_CLIENT
    • sourceBuildSourceRequired
      Show child attributes
      • uploadUploadSourceOne of source
      • steam_cmdSteamCmdSourceOne of source
      • archiveArchiveSourceOne of source
      • container_imageContainerImageSourceOne of source
      • install_commandsrepeated string

        Commands run after the artifacts are in place, in order.

        The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

    • namestringIdentifier

      accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

      Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

      The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

    • versionstring

      Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

    • operating_systemOperatingSystem

      Operating system the build's artifacts target.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • labelsmap<string, string>
  • update_maskFieldMaskRequired

Returns

Build.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"build": {
"display_name": "My server",
"kind": "KIND_SERVER",
"source": {}
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/UpdateBuild
Example response
{
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"upload": {
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
},
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

DeleteBuild

plany.game.v1.GameRegistryService/DeleteBuild

Parameters

  • namestringRequired
  • forcebool

    Delete even if games still reference it. Those games stop being launchable; workloads already running are unaffected, because they pinned their build when they were created.

Returns

Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "builds/my-build"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/DeleteBuild
Example response
{}

GetBuildUploadUrl

plany.game.v1.GameRegistryService/GetBuildUploadUrl

Returns a fresh signed upload URL for an UPLOAD build.

Separate from CreateBuild because signed URLs expire and uploads of this size fail: a customer pushing 8GB over a domestic connection should be able to ask for another URL rather than start again with a new build.

Parameters

  • namestringRequired
  • How long the URL should last. Capped by policy.

  • checksum_sha256string

    Hex SHA-256 of the archive the client is about to send.

    Signed into the URL when given, which makes storage itself refuse an archive that does not hash to it. That is stronger than comparing the two afterwards: a corrupted upload never lands, so there is no window in which a bad object exists and nothing to unwind.

    Declared here rather than only on the build because the file is chosen after the build is created — a client picks it, hashes it, and asks for a URL for that exact archive. It is recorded on the build when the upload is finalized.

Returns

GetBuildUploadUrlResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "builds/my-build"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/GetBuildUploadUrl
Example response
{
"upload_url": "",
"expire_time": "2026-10-04T12:00:00Z",
"required_headers": {
"key": ""
}
}

FinalizeBuild

plany.game.v1.GameRegistryService/FinalizeBuild

Marks an upload complete, moving the build towards READY.

Called by the client after the PUT succeeds. Plany could poll storage instead, but a customer who has just finished an hour-long upload should not wait on a sweep to find out.

Parameters

  • namestringRequired
  • checksum_sha256string

    Hex SHA-256 of what was uploaded, verified against the stored object.

Returns

Build.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "builds/my-build"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/FinalizeBuild
Example response
{
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"upload": {
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
},
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

GetBuildDownloadUrl

plany.game.v1.GameRegistryService/GetBuildDownloadUrl

Returns a short-lived URL to download a build's archive from.

Called from inside a running server, as that server's own identity, when it installs its build. Because the URL is issued on request rather than stored, it is always current — and a server whose access has been revoked gets nothing.

Parameters

  • namestringRequired

Returns

GetBuildDownloadUrlResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "builds/my-build"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/GetBuildDownloadUrl
Example response
{
"download_url": "",
"expire_time": "2026-10-04T12:00:00Z",
"checksum_sha256": ""
}

CreateGame

plany.game.v1.GameRegistryService/CreateGame

Parameters

  • parentstringRequired
  • gameGameRequired
    Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      games/{game} or accounts/{account}/games/{game}.

    • descriptionstring
    • parentstring

      The game this one refines. Empty for a root such as "Minecraft".

      A game may descend from a Plany-published game even when it is a customer's own — that is the point of the field.

    • versionstring

      Free-form version label for this node, e.g. "1.20.4".

    • How this game runs as a dedicated server. Deployed by plany.playpute.v1.

      Absent on a game nobody hosts — a single-player title a customer streams has no server half, and inventing an empty one would make every picker in Playpute offer a game it cannot run.

      Show child attributes
      • buildstring

        Artifacts the server runs. Must be a KIND_SERVER build.

      • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

    • How this game runs as a playable client. Absent on a game that declares no client.

      Show child attributes
      • buildstring

        Artifacts to install. Must be a KIND_CLIENT build.

      • launchrepeated string

        The command, as an argv, relative to the root of the unpacked build.

        Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>

        Environment for the game, on top of the machine's own.

        Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

    • labelsmap<string, string>
  • game_idstring
  • request_idstring

Returns

Game.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"game": {
"display_name": "My server"
}
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/CreateGame
Example response
{
"name": "games/my-game",
"display_name": "My server",
"description": "",
"parent": "games/my-game",
"version": "",
"server": {
"build": "builds/my-build",
"runtime": {
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0
}
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_launchable": false,
"client_launchable": false,
"system": false,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

GetGame

Read
plany.game.v1.GameRegistryService/GetGame

Parameters

  • namestringRequired

Returns

Game.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "games/my-game"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/GetGame
Example response
{
"name": "games/my-game",
"display_name": "My server",
"description": "",
"parent": "games/my-game",
"version": "",
"server": {
"build": "builds/my-build",
"runtime": {
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0
}
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_launchable": false,
"client_launchable": false,
"system": false,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

ListGames

Read
plany.game.v1.GameRegistryService/ListGames

Lists games visible to an account: its own, plus every Plany-published one.

Both in one call because that is the list a customer wants to see. Making them ask twice and merge would push the tree's shape into every client.

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring
  • parent_gamestring

    Return only the direct children of this game. Empty returns every visible game, which is what a search box wants; set it to walk the tree a level at a time, which is what a picker wants.

  • launchable_forKind

    Return only games whose named half can actually be deployed. KIND_SERVER is the list a game server picker wants. Unspecified returns branch nodes too, which is what a catalogue browser wants.

    KIND_SERVERKIND_CLIENT
  • exclude_systembool

    Leave out Plany-published games.

Returns

ListGamesResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"page_size": 50
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/ListGames
Example response
{
"games": [
{
"name": "games/my-game",
"display_name": "My server",
"description": "",
"parent": "games/my-game",
"version": "",
"server": {
"build": "builds/my-build"
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_launchable": false,
"client_launchable": false,
"system": false,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}
],
"next_page_token": ""
}

UpdateGame

plany.game.v1.GameRegistryService/UpdateGame

Parameters

  • gameGameRequired
    Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      games/{game} or accounts/{account}/games/{game}.

    • descriptionstring
    • parentstring

      The game this one refines. Empty for a root such as "Minecraft".

      A game may descend from a Plany-published game even when it is a customer's own — that is the point of the field.

    • versionstring

      Free-form version label for this node, e.g. "1.20.4".

    • How this game runs as a dedicated server. Deployed by plany.playpute.v1.

      Absent on a game nobody hosts — a single-player title a customer streams has no server half, and inventing an empty one would make every picker in Playpute offer a game it cannot run.

      Show child attributes
      • buildstring

        Artifacts the server runs. Must be a KIND_SERVER build.

      • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

    • How this game runs as a playable client. Absent on a game that declares no client.

      Show child attributes
      • buildstring

        Artifacts to install. Must be a KIND_CLIENT build.

      • launchrepeated string

        The command, as an argv, relative to the root of the unpacked build.

        Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>

        Environment for the game, on top of the machine's own.

        Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

    • labelsmap<string, string>
  • update_maskFieldMaskRequired

    Required.

    server and client are each replaced wholesale when they are in the mask, the way plany.playpute.v1.UpdateGameServer treats a message field. A client showing three of a runtime's fields therefore has to read the current game and merge, or a form that never displayed config_files silently deletes them.

Returns

Game.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"game": {
"display_name": "My server"
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/UpdateGame
Example response
{
"name": "games/my-game",
"display_name": "My server",
"description": "",
"parent": "games/my-game",
"version": "",
"server": {
"build": "builds/my-build",
"runtime": {
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0
}
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_launchable": false,
"client_launchable": false,
"system": false,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

DeleteGame

plany.game.v1.GameRegistryService/DeleteGame

Parameters

  • namestringRequired
  • forcebool

    Delete descendants too. Without it, deleting a game that has children is refused rather than orphaning them.

Returns

Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "games/my-game"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/DeleteGame
Example response
{}

ResolveGame

plany.game.v1.GameRegistryService/ResolveGame

Returns a game with every inherited field resolved, both halves at once.

This is what a settings form should be rendered from, and what a game server is created from. One call returns both halves, so they always come from the same version of the game.

Parameters

  • namestringRequired

Returns

ResolveGameResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "games/my-game"
}' \
api.plany.cloud:443 plany.game.v1.GameRegistryService/ResolveGame
Example response
{
"game": {
"name": "games/my-game",
"display_name": "My server",
"description": "",
"parent": "games/my-game",
"version": "",
"server": {
"build": "builds/my-build"
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_launchable": false,
"client_launchable": false,
"system": false,
"labels": {
"key": ""
},
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
},
"server": {
"build": "builds/my-build",
"runtime": {
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0
}
},
"client": {
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
},
"server_build": {
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
},
"client_build": {
"name": "builds/my-build",
"display_name": "My server",
"kind": "KIND_SERVER",
"version": "",
"source": {
"install_commands": [
""
]
},
"state": "STATE_PENDING_UPLOAD",
"error": {},
"size_bytes": "0",
"operating_system": "OPERATING_SYSTEM_LINUX",
"labels": {
"key": ""
},
"system": false,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
},
"inherited_from": [
""
]
}

The ArchiveSource object

ArchiveSource fetches artifacts from a URL.

For vendors that publish a build directly — Mojang's server jar, a Forge installer, a modpack zip. Nothing is mirrored: the URL is fetched when a workload is provisioned, so the vendor's terms are between them and the customer.

Attributes

  • urlstringRequired
  • checksum_sha256string

    Hex SHA-256 of the download. Optional, and the difference between "this is the build I tested" and "this is whatever is at that URL today".

  • extractbool

    Unpack the download. False leaves it in place, which is what a bare server.jar wants.

  • headersmap<string, string>Input only

    Extra headers, for a vendor that requires a token. Write-only.

ArchiveSource
{
"url": "",
"checksum_sha256": "",
"extract": false
}

The BuildSource object

BuildSource says where a build's artifacts come from.

Attributes

  • uploadUploadSourceOne of source
    Show child attributes
    • upload_urlstringOutput only

      Where the client PUTs the archive. Output-only and short-lived; call GetBuildUploadUrl for a fresh one.

    • upload_url_expire_timeTimestampOutput only
    • objectstringOutput only

      Storage path once uploaded.

    • checksum_sha256string

      Hex SHA-256 of the archive, checked on arrival.

      Optional, and worth setting: given at presign time it is signed into the URL, so storage itself refuses an archive that does not hash to it. A corrupted upload never lands, which is stronger than comparing afterwards — there is no window in which a bad object exists and nothing to unwind.

  • steam_cmdSteamCmdSourceOne of source
    Show child attributes
    • app_idint64Required
    • branchstring

      Non-default branch, e.g. "prerelease". Empty takes the public branch.

    • branch_passwordstringInput only

      Password for a private branch. Write-only: it is stored encrypted and never returned.

    • usernamestring

      Steam account for downloads that refuse anonymous access. Empty uses anonymous, which covers most dedicated servers and almost no game clients — a client build is usually somebody's own licensed copy.

    • passwordstringInput only

      Write-only, stored encrypted.

    • validatebool

      Validate the install after download. Slower, and worth it on a build that will be copied to many machines.

  • archiveArchiveSourceOne of source
    Show child attributes
    • urlstringRequired
    • checksum_sha256string

      Hex SHA-256 of the download. Optional, and the difference between "this is the build I tested" and "this is whatever is at that URL today".

    • extractbool

      Unpack the download. False leaves it in place, which is what a bare server.jar wants.

    • headersmap<string, string>Input only

      Extra headers, for a vendor that requires a token. Write-only.

  • container_imageContainerImageSourceOne of source
    Show child attributes
    • imagestringRequired

      The reference as written, e.g. eu-west-2.plany.cr/my-project/lobby:1.4 or us-docker.pkg.dev/agones-images/examples/simple-game-server:0.35.

      A reference that already names a digest is taken as it is.

    • digeststringOutput only

      sha256:…, resolved when the build was created.

  • install_commandsrepeated string

    Commands run after the artifacts are in place, in order.

    The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

BuildSource
{
"upload": {
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
},
"install_commands": [
""
]
}

The ClientSpec object

ClientSpec is a game's playable-client half.

Much smaller than ServerSpec, deliberately: a dedicated server is configured by whoever runs it — ports, files, settings — while a client is configured by the person playing it, through the game's own menus.

Attributes

  • buildstring

    Artifacts to install. Must be a KIND_CLIENT build.

  • launchrepeated string

    The command, as an argv, relative to the root of the unpacked build.

    Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

  • working_directorystring

    Working directory relative to the build root. Empty means the root.

  • environmentmap<string, string>

    Environment for the game, on top of the machine's own.

    Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

ClientSpec
{
"build": "builds/my-build",
"launch": [
""
],
"working_directory": "",
"environment": {
"key": ""
}
}

The ConfigFile object

ConfigFile is a file written into the build before launch.

Attributes

  • pathstringRequired

    Path relative to the build root.

  • contentsstringRequired

    Contents. ${VAR} is substituted from the runtime environment and the server's settings, which is how one template serves every server.

  • modeint32

    Unix mode, e.g. 0644. Zero takes 0644.

  • preserve_existingbool

    Leave an existing file alone rather than overwriting it.

    Matters on a restart: server.properties is edited by admins in-game, and rewriting it every boot would silently discard their changes.

ConfigFile
{
"path": "",
"contents": "",
"mode": 0,
"preserve_existing": false
}

The ContainerImageSource object

ContainerImageSource is a container image, run as the game server.

Resolved once, when the build is created

image is what the customer wrote, and digest is what it pointed at when this build was created. Everything that runs the build pulls the digest, so a build is a promise about bytes: a tag pushed over afterwards changes nothing already running, and two members of a fleet created an hour apart run the same image. A customer who pushes a new image makes a new build, which is exactly what rolling a fleet onto it is.

Where it can come from

Plany's own registry, <region>.plany.cr/{project}/{repository}, pulled by the game server as itself — its identity is granted roles/registry.puller on that one repository. Or any public registry, pulled anonymously. A private registry elsewhere needs a credential the platform has nowhere to hold yet, and is refused when the build is created rather than when a server fails to start.

There is nothing to install

A container build is READY as soon as it resolves. install_commands are refused on one: the image is the install, and a command run after the pull would be an install step every member repeats — which is the cold start the warm-up capture exists to remove.

Attributes

  • imagestringRequired

    The reference as written, e.g. eu-west-2.plany.cr/my-project/lobby:1.4 or us-docker.pkg.dev/agones-images/examples/simple-game-server:0.35.

    A reference that already names a digest is taken as it is.

  • digeststringOutput only

    sha256:…, resolved when the build was created.

ContainerImageSource
{
"image": "",
"digest": ""
}

The ContainerRuntime object

ContainerRuntime overrides a container image's own entrypoint and command.

Field by field, exactly as Kubernetes and Docker resolve it: command replaces the image's entrypoint and args replaces its command, and setting only command keeps the image's command. Anything else would surprise somebody who has written a pod spec before, and every Autopilot customer has.

Attributes

  • commandrepeated string
  • argsrepeated string
  • working_directorystring

    The container's working directory, absolute inside the image. Empty keeps the image's own. Separate from GameRuntime.working_directory, which is a path relative to an installed build and means nothing inside an image.

ContainerRuntime
{
"command": [
""
],
"args": [
""
],
"working_directory": ""
}

The GameRuntime object

GameRuntime is everything needed to turn server artifacts into a running server.

Every field is individually inheritable. A child game that sets only launch_command keeps its parent's ports, resources and config files, which is what makes "Forge 1.20.4" a three-line definition rather than a copy of everything Minecraft needs.

Attributes

  • launch_commandrepeated string

    Command that starts the server, run in the build's directory.

    Run directly with its arguments, not through a shell, so pipes, redirects and && have no special meaning. ${VAR} is substituted from environment first.

  • working_directorystring

    Working directory relative to the build root. Empty means the root.

  • environmentmap<string, string>
  • Show child attributes
    • namestringRequired

      Stable identifier, e.g. "game", "rcon", "query". Referenced by connection info on a running server, so it must not change between versions of a game.

    • portint32Required
    • PROTOCOL_TCPPROTOCOL_UDP
    • publicbool

      Reachable from the internet. False keeps it inside the VM — the right default for RCON, which is a remote shell with a password in front of it.

  • Files written before launch, e.g. server.properties, eula.txt.

    Show child attributes
    • pathstringRequired

      Path relative to the build root.

    • contentsstringRequired

      Contents. ${VAR} is substituted from the runtime environment and the server's settings, which is how one template serves every server.

    • modeint32

      Unix mode, e.g. 0644. Zero takes 0644.

    • preserve_existingbool

      Leave an existing file alone rather than overwriting it.

      Matters on a restart: server.properties is edited by admins in-game, and rewriting it every boot would silently discard their changes.

  • Default size of a server running this game. A customer may ask for more.

    Show child attributes
    • cpuCpuSpecRequired
      Show child attributes
      • vcpusint32Required

        Number of virtual CPUs the workload sees. Required, must be at least 1.

      • reserved_millisint64

        CPU time reserved on the host, in millicores (1000 = one full core).

        Must be <= vcpus * 1000. Zero means "reserve the full vcpus * 1000", i.e. no oversubscription. Below that, the VM is burstable and the difference is the burst headroom.

      • limit_millisint64

        Hard ceiling on host CPU time, in millicores, enforced by the agent via cgroup cpu.max. Zero means the ceiling is vcpus * 1000. Set this below vcpus * 1000 to cap a burstable VM that would otherwise consume all idle capacity on the node.

      • architectureCpuArchitecture
        CPU_ARCHITECTURE_X86_64CPU_ARCHITECTURE_ARM64
      • required_featuresrepeated string

        CPUID feature flags the workload requires, lowercase as they appear in /proc/cpuinfo — e.g. "avx2", "aes". Placement rejects nodes lacking any of them. Anti-cheat and DRM in game servers occasionally depend on these.

      • dedicated_coresbool

        Pin each vCPU to a distinct physical core and let no other workload share those cores. Removes noisy-neighbour jitter for latency-sensitive tick loops, at the cost of a dedicated-core price.

      • isolate_smt_siblingsbool

        Require SMT siblings of the pinned cores to stay idle. Only meaningful with dedicated_cores; used for workloads that are sensitive to hyperthread contention or that need side-channel isolation.

    • memoryMemorySpecRequired
      Show child attributes
      • size_bytesint64Required

        Memory the workload sees, in bytes. Required.

      • reserved_bytesint64

        Memory guaranteed to the workload, in bytes. Must be no more than size_bytes. Zero means all of size_bytes is guaranteed.

        Reserving less than size_bytes requires balloon_enabled, so unused memory can be reclaimed when it is needed elsewhere.

      • balloon_enabledbool

        Allow memory the workload is not using to be reclaimed. Required when reserved_bytes is less than size_bytes.

      • hugepagesbool

        Back the workload's memory with 2 MiB pages. Noticeably faster for memory-heavy servers — large voxel worlds, big entity counts — but can only be placed where such memory is available.

      • hotplug_max_bytesint64

        Allow memory to grow to this size while running, without a restart. Zero disables it. Must be at least size_bytes when set.

      • sharedbool

        Allow identical memory pages to be shared with other workloads on the same machine. Saves memory when many servers run the same game, at some CPU cost and with weaker isolation between them.

    • Block devices, in attachment order. Exactly one must set boot unless the workload boots from an initramfs alone.

      Show child attributes
      • disk_idstringRequired

        Identifier for this disk within the workload, e.g. "root" or "world-data". Must be unique within it.

      • sourceDiskSpec.SourceRequired
      • size_bytesint64

        Size of the device. Required for a blank disk; for an image or snapshot source, zero means "the source's own size" and any larger value grows the filesystem on first boot.

      • DISK_TYPE_LOCAL_NVMEDISK_TYPE_NETWORK_SSDDISK_TYPE_NETWORK_SSD_HIGH_IOPS
      • read_onlybool

        Attach read-only. Several instances may share one read-only volume, which is how a common asset bundle is mounted into many game servers at once.

      • bootbool

        Marks the disk the workload boots from. Exactly one disk may set this.

      • delete_on_instance_deletebool

        Delete the underlying storage when the instance is deleted. Always true in effect for LOCAL_NVME.

      • direct_iobool

        Use direct IO (O_DIRECT), bypassing the host page cache. Lowers memory pressure on the node and makes latency more predictable, at the cost of losing host-side caching.

    • Show child attributes
      • interface_idstringRequired

        Stable identifier within the instance, e.g. "eth0".

      • networkstring

        Private network to attach to, as a resource name. Empty means the project's default network in this location.

      • private_ipv4string

        Requested private IPv4 address. Empty allocates one from the subnet.

      • PUBLIC_ADDRESS_MODE_NONEPUBLIC_ADDRESS_MODE_SHARED_IPV4PUBLIC_ADDRESS_MODE_DEDICATED_IPV4PUBLIC_ADDRESS_MODE_IPV6
      • NETWORK_TIER_STANDARDNETWORK_TIER_PREMIUM
      • mac_addressstring

        The interface's MAC address. Empty generates one. Pinning it matters for game licences tied to a MAC.

      • multi_queuebool

        Enable multi-queue virtio-net with one queue pair per vCPU. Raises packet throughput for servers handling many concurrent clients.

      • tagsrepeated string

        Network tags, which firewall rules on this interface's network target.

        Per interface rather than per instance because a rule belongs to one network, and an instance with an interface on each of two networks is answerable to two sets of rules. Lowercase letters, digits and hyphens, up to 63 characters each.

      • deny_inboundbool

        Refuse every inbound connection on this interface, whatever the network's firewall rules say. Replies to connections the workload opened still arrive.

        For an interface that exists so a workload can reach a network rather than be reached on it — a sandbox connected to one of your networks, for example.

      • no_default_routebool

        Send no internet traffic and no DNS through this interface: only the network's own range is reached through it. Without this, a workload with two interfaces could send its internet traffic out of either.

    • placementPlacementSpec
      Show child attributes
      • zonesrepeated string

        Zones the instance may land in, as location ids ("eu-west-2a"). Empty means any zone in the region. More than one entry is a preference list in priority order, not a hard set.

      • required_node_selectorsrepeated NodeSelectorRequirement

        Hard node requirements. A node must satisfy every entry.

      • preferred_node_selectorsrepeated NodeSelectorRequirement

        Soft node preferences. Nodes satisfying more of these score higher, but none of them can make placement fail.

      • placement_groupstring

        Group this workload belongs to, scoped to the project. Workloads sharing a group are spread out or packed together according to policy.

      • PLACEMENT_POLICY_PACKPLACEMENT_POLICY_SPREADPLACEMENT_POLICY_STRICT_SPREAD_NODEPLACEMENT_POLICY_STRICT_SPREAD_ZONE
      • capacity_classstring

        Class of capacity to draw from. Leave empty to let Plany choose, which is right for almost every workload.

      • disallow_preemptiblebool

        Refuse to place onto pre-emptible (spot) capacity. Spot is materially cheaper and fine for a dev server, but wrong for a ranked match in progress.

      • nodestring

        Pin to one node by resource name. Bypasses scoring entirely; intended for debugging and for rescheduling a VM back onto the node holding its local disk.

    • schedulingSchedulingSpec
      Show child attributes
      • ON_HOST_MAINTENANCE_MIGRATEON_HOST_MAINTENANCE_TERMINATE
      • RESTART_POLICY_NEVERRESTART_POLICY_ALWAYSRESTART_POLICY_ON_FAILURE
      • preemptiblebool

        Run as spot: on spare capacity, at the spot rate, reclaimable with two minutes' notice when an on-demand workload needs the room.

      • preemption_noticeDuration

        Warning given before a spot reclaim, readable at /metadata/spot/instance-action on the metadata service. The notice is always two minutes; leave this unset.

      • max_run_durationDuration

        Stop the instance automatically once it has run this long. Zero means no limit. This is the guard rail that stops a forgotten dev server draining a hobby account's credit overnight.

      • termination_grace_periodDuration

        Time between the shutdown signal and a forced stop, so a game server can save its world. Zero uses the default of thirty seconds.

      • preemptible_fallbackbool

        With preemptible: place as an ordinary on-demand workload when no spare capacity fits, rather than waiting for some. The allocation says which happened, and it is what the instance is billed at.

  • startup_timeoutDuration

    How long to allow for start-up before declaring the server unhealthy.

    Generous by necessity: a modded Minecraft server can take minutes to generate a world on first boot, and killing it halfway leaves a corrupt save.

  • stop_signalstring

    Signal used to ask the server to exit, e.g. "SIGTERM".

  • stop_timeoutDuration

    Time allowed for a clean shutdown before the process is killed. Game servers write world state on exit; cutting that short loses player progress.

  • Settings a player-facing UI may expose, e.g. max players or difficulty.

    Show child attributes
    • keystringRequired

      Key, referenced as ${key} from config files and the launch command.

    • display_namestring
    • descriptionstring
    • TYPE_STRINGTYPE_INTTYPE_BOOLTYPE_ENUM
    • default_valuestring
    • allowed_valuesrepeated string

      Permitted values, for TYPE_ENUM.

    • min_valueint64

      Bounds, for TYPE_INT.

    • max_valueint64
    • requires_restartbool

      Requires a restart to take effect.

  • operating_systemOperatingSystem

    Operating system the launch command expects.

    OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
  • max_playersint32

    How many players one server of this game holds.

    The game's own declaration, inherited down the catalogue like everything else here — Minecraft says twenty, and a Forge variant of it says twenty unless it says otherwise.

    It exists for autoscaling: "keep servers 70% full" needs a denominator, and there was nowhere on the platform that held one. Zero means unknown, and unknown is honoured rather than guessed — a group scaling on a percentage of an invented capacity would scale on a number the customer never gave. Such a group falls back to the terms that need no denominator: waiting connections, and CPU.

    Deliberately not read from the game's own settings — max-players in server.properties is a string a customer edits per server, and a fleet whose denominator changed per member would produce a different target for each of them.

  • sdk_healthSdkHealth

    How the platform decides a server has stopped answering, for a game that uses the Agones SDK's Health().

    Absent is off, and that is the right default rather than a gap: a game that never calls Health() would otherwise be declared unhealthy on a timer and replaced forever. Agones' defaults (5 seconds, 3 failures) are what the Autopilot importer writes when a manifest leaves health unset.

    Show child attributes
    • period_secondsint32

      Seconds between the pings a healthy server sends. Defaults to 5.

    • failure_thresholdint32

      Consecutive missed periods before the server is unhealthy. Defaults to 3.

    • initial_delay_secondsint32

      Seconds after the game starts before a missed ping counts. Defaults to 5.

  • Overrides for a container build's entrypoint and arguments.

    Only meaningful with a ContainerImageSource build, where launch_command is not used: a container has an entrypoint and a command of its own, and Kubernetes' rule for overriding them is not "replace the whole argv". See ContainerRuntime.

    Show child attributes
    • commandrepeated string
    • argsrepeated string
    • working_directorystring

      The container's working directory, absolute inside the image. Empty keeps the image's own. Separate from GameRuntime.working_directory, which is a path relative to an installed build and means nothing inside an image.

GameRuntime
{
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"ports": [
{
"name": "",
"port": 0,
"protocol": "PROTOCOL_TCP",
"public": false
}
],
"config_files": [
{
"path": "",
"contents": "",
"mode": 0,
"preserve_existing": false
}
],
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"source": {
"image": ""
},
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"io_limits": {
"bandwidth_bytes_per_second": "0",
"bandwidth_burst_bytes": "0",
"iops": "0",
"iops_burst": "0"
},
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"rate_limits": {
"ingress_bits_per_second": "0",
"egress_bits_per_second": "0",
"ingress_burst_bits": "0",
"egress_burst_bits": "0",
"ingress_packets_per_second": "0",
"egress_packets_per_second": "0"
},
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"required_node_selectors": [
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}
],
"preferred_node_selectors": [
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"settings": [
{
"key": "",
"display_name": "My server",
"description": "",
"type": "TYPE_STRING",
"default_value": "",
"allowed_values": [
""
],
"min_value": "0",
"max_value": "0",
"requires_restart": false
}
],
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0,
"sdk_health": {
"period_seconds": 0,
"failure_threshold": 0,
"initial_delay_seconds": 0
},
"container": {
"command": [
""
],
"args": [
""
],
"working_directory": ""
}
}

The GameSetting object

GameSetting is a knob a server operator can turn.

Declared by the game so a console can render a form for any game without knowing anything about it.

Attributes

  • keystringRequired

    Key, referenced as ${key} from config files and the launch command.

  • display_namestring
  • descriptionstring
  • TYPE_STRINGTYPE_INTTYPE_BOOLTYPE_ENUM
  • default_valuestring
  • allowed_valuesrepeated string

    Permitted values, for TYPE_ENUM.

  • min_valueint64

    Bounds, for TYPE_INT.

  • max_valueint64
  • requires_restartbool

    Requires a restart to take effect.

GameSetting
{
"key": "",
"display_name": "My server",
"description": "",
"type": "TYPE_STRING",
"default_value": "",
"allowed_values": [
""
],
"min_value": "0",
"max_value": "0",
"requires_restart": false
}

The PortMapping object

PortMapping is a port the server listens on.

Attributes

  • namestringRequired

    Stable identifier, e.g. "game", "rcon", "query". Referenced by connection info on a running server, so it must not change between versions of a game.

  • portint32Required
  • PROTOCOL_TCPPROTOCOL_UDP
  • publicbool

    Reachable from the internet. False keeps it inside the VM — the right default for RCON, which is a remote shell with a password in front of it.

PortMapping
{
"name": "",
"port": 0,
"protocol": "PROTOCOL_TCP",
"public": false
}

The SdkHealth object

SdkHealth is Agones' GameServer.spec.health, in Plany's vocabulary.

Attributes

  • period_secondsint32

    Seconds between the pings a healthy server sends. Defaults to 5.

  • failure_thresholdint32

    Consecutive missed periods before the server is unhealthy. Defaults to 3.

  • initial_delay_secondsint32

    Seconds after the game starts before a missed ping counts. Defaults to 5.

SdkHealth
{
"period_seconds": 0,
"failure_threshold": 0,
"initial_delay_seconds": 0
}

The ServerSpec object

ServerSpec is a game's dedicated-server half.

Attributes

  • buildstring

    Artifacts the server runs. Must be a KIND_SERVER build.

  • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

    Show child attributes
    • launch_commandrepeated string

      Command that starts the server, run in the build's directory.

      Run directly with its arguments, not through a shell, so pipes, redirects and && have no special meaning. ${VAR} is substituted from environment first.

    • working_directorystring

      Working directory relative to the build root. Empty means the root.

    • environmentmap<string, string>
    • Show child attributes
      • namestringRequired

        Stable identifier, e.g. "game", "rcon", "query". Referenced by connection info on a running server, so it must not change between versions of a game.

      • portint32Required
      • PROTOCOL_TCPPROTOCOL_UDP
      • publicbool

        Reachable from the internet. False keeps it inside the VM — the right default for RCON, which is a remote shell with a password in front of it.

    • Files written before launch, e.g. server.properties, eula.txt.

      Show child attributes
      • pathstringRequired

        Path relative to the build root.

      • contentsstringRequired

        Contents. ${VAR} is substituted from the runtime environment and the server's settings, which is how one template serves every server.

      • modeint32

        Unix mode, e.g. 0644. Zero takes 0644.

      • preserve_existingbool

        Leave an existing file alone rather than overwriting it.

        Matters on a restart: server.properties is edited by admins in-game, and rewriting it every boot would silently discard their changes.

    • Default size of a server running this game. A customer may ask for more.

      Show child attributes
    • startup_timeoutDuration

      How long to allow for start-up before declaring the server unhealthy.

      Generous by necessity: a modded Minecraft server can take minutes to generate a world on first boot, and killing it halfway leaves a corrupt save.

    • stop_signalstring

      Signal used to ask the server to exit, e.g. "SIGTERM".

    • stop_timeoutDuration

      Time allowed for a clean shutdown before the process is killed. Game servers write world state on exit; cutting that short loses player progress.

    • Settings a player-facing UI may expose, e.g. max players or difficulty.

      Show child attributes
      • keystringRequired

        Key, referenced as ${key} from config files and the launch command.

      • display_namestring
      • descriptionstring
      • TYPE_STRINGTYPE_INTTYPE_BOOLTYPE_ENUM
      • default_valuestring
      • allowed_valuesrepeated string

        Permitted values, for TYPE_ENUM.

      • min_valueint64

        Bounds, for TYPE_INT.

      • max_valueint64
      • requires_restartbool

        Requires a restart to take effect.

    • operating_systemOperatingSystem

      Operating system the launch command expects.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • max_playersint32

      How many players one server of this game holds.

      The game's own declaration, inherited down the catalogue like everything else here — Minecraft says twenty, and a Forge variant of it says twenty unless it says otherwise.

      It exists for autoscaling: "keep servers 70% full" needs a denominator, and there was nowhere on the platform that held one. Zero means unknown, and unknown is honoured rather than guessed — a group scaling on a percentage of an invented capacity would scale on a number the customer never gave. Such a group falls back to the terms that need no denominator: waiting connections, and CPU.

      Deliberately not read from the game's own settings — max-players in server.properties is a string a customer edits per server, and a fleet whose denominator changed per member would produce a different target for each of them.

    • sdk_healthSdkHealth

      How the platform decides a server has stopped answering, for a game that uses the Agones SDK's Health().

      Absent is off, and that is the right default rather than a gap: a game that never calls Health() would otherwise be declared unhealthy on a timer and replaced forever. Agones' defaults (5 seconds, 3 failures) are what the Autopilot importer writes when a manifest leaves health unset.

      Show child attributes
      • period_secondsint32

        Seconds between the pings a healthy server sends. Defaults to 5.

      • failure_thresholdint32

        Consecutive missed periods before the server is unhealthy. Defaults to 3.

      • initial_delay_secondsint32

        Seconds after the game starts before a missed ping counts. Defaults to 5.

    • Overrides for a container build's entrypoint and arguments.

      Only meaningful with a ContainerImageSource build, where launch_command is not used: a container has an entrypoint and a command of its own, and Kubernetes' rule for overriding them is not "replace the whole argv". See ContainerRuntime.

      Show child attributes
      • commandrepeated string
      • argsrepeated string
      • working_directorystring

        The container's working directory, absolute inside the image. Empty keeps the image's own. Separate from GameRuntime.working_directory, which is a path relative to an installed build and means nothing inside an image.

ServerSpec
{
"build": "builds/my-build",
"runtime": {
"launch_command": [
""
],
"working_directory": "",
"environment": {
"key": ""
},
"ports": [
{
"name": "",
"port": 0,
"protocol": "PROTOCOL_TCP",
"public": false
}
],
"config_files": [
{
"path": "",
"contents": "",
"mode": 0,
"preserve_existing": false
}
],
"resources": {
"cpu": {
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
},
"memory": {
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
},
"disks": [
{
"disk_id": "my-disk",
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"direct_io": false
}
],
"network_interfaces": [
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}
],
"placement": {
"zones": [
""
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
},
"scheduling": {
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}
},
"startup_timeout": "300s",
"stop_signal": "",
"stop_timeout": "300s",
"settings": [
{
"key": "",
"display_name": "My server",
"description": "",
"type": "TYPE_STRING",
"default_value": "",
"allowed_values": [
""
],
"min_value": "0",
"max_value": "0",
"requires_restart": false
}
],
"operating_system": "OPERATING_SYSTEM_LINUX",
"max_players": 0,
"sdk_health": {
"period_seconds": 0,
"failure_threshold": 0,
"initial_delay_seconds": 0
},
"container": {
"command": [
""
],
"args": [
""
],
"working_directory": ""
}
}
}

The SteamCmdSource object

SteamCmdSource installs from Steam.

The simplification the brief asks for: for the large family of Source and Steamworks games, an app id is the entire configuration.

Which app id depends on the build's kind, and that is the whole reason this registry exists. Garry's Mod is 4000 to play and 4020 to host: two apps, one game, and until the two catalogues became one there was nowhere to say so. A KIND_SERVER build takes the dedicated server's id and a KIND_CLIENT build takes the game's, and they hang off the same node in the tree.

Attributes

  • app_idint64Required
  • branchstring

    Non-default branch, e.g. "prerelease". Empty takes the public branch.

  • branch_passwordstringInput only

    Password for a private branch. Write-only: it is stored encrypted and never returned.

  • usernamestring

    Steam account for downloads that refuse anonymous access. Empty uses anonymous, which covers most dedicated servers and almost no game clients — a client build is usually somebody's own licensed copy.

  • passwordstringInput only

    Write-only, stored encrypted.

  • validatebool

    Validate the install after download. Slower, and worth it on a build that will be copied to many machines.

SteamCmdSource
{
"app_id": "0",
"branch": "",
"username": "",
"validate": false
}

The UploadSource object

UploadSource stores artifacts in Plany's object storage.

CreateBuild returns a signed upload URL, and the build stays in PENDING_UPLOAD until the bytes arrive. This is the only source that costs storage, and the only one a customer has to actively feed.

Attributes

  • upload_urlstringOutput only

    Where the client PUTs the archive. Output-only and short-lived; call GetBuildUploadUrl for a fresh one.

  • upload_url_expire_timeTimestampOutput only
  • objectstringOutput only

    Storage path once uploaded.

  • checksum_sha256string

    Hex SHA-256 of the archive, checked on arrival.

    Optional, and worth setting: given at presign time it is signed into the URL, so storage itself refuses an archive that does not hash to it. A corrupted upload never lands, which is stronger than comparing afterwards — there is no window in which a bad object exists and nothing to unwind.

UploadSource
{
"upload_url": "",
"upload_url_expire_time": "2026-10-04T12:00:00Z",
"object": "",
"checksum_sha256": ""
}

The CpuSpec object

CpuSpec describes the processor a workload needs.

Two numbers, deliberately separate. vcpus is how many processors the workload sees. reserved_millis is how much CPU time it is guaranteed. A 4-vCPU game server reserving 2000 millis is guaranteed two cores' worth of time and may burst into idle capacity beyond that — which is what makes cheaper sizes possible.

Attributes

  • vcpusint32Required

    Number of virtual CPUs the workload sees. Required, must be at least 1.

  • reserved_millisint64

    CPU time reserved on the host, in millicores (1000 = one full core).

    Must be <= vcpus * 1000. Zero means "reserve the full vcpus * 1000", i.e. no oversubscription. Below that, the VM is burstable and the difference is the burst headroom.

  • limit_millisint64

    Hard ceiling on host CPU time, in millicores, enforced by the agent via cgroup cpu.max. Zero means the ceiling is vcpus * 1000. Set this below vcpus * 1000 to cap a burstable VM that would otherwise consume all idle capacity on the node.

  • architectureCpuArchitecture
    CPU_ARCHITECTURE_X86_64CPU_ARCHITECTURE_ARM64
  • required_featuresrepeated string

    CPUID feature flags the workload requires, lowercase as they appear in /proc/cpuinfo — e.g. "avx2", "aes". Placement rejects nodes lacking any of them. Anti-cheat and DRM in game servers occasionally depend on these.

  • dedicated_coresbool

    Pin each vCPU to a distinct physical core and let no other workload share those cores. Removes noisy-neighbour jitter for latency-sensitive tick loops, at the cost of a dedicated-core price.

  • isolate_smt_siblingsbool

    Require SMT siblings of the pinned cores to stay idle. Only meaningful with dedicated_cores; used for workloads that are sensitive to hyperthread contention or that need side-channel isolation.

CpuSpec
{
"vcpus": 0,
"reserved_millis": "0",
"limit_millis": "0",
"architecture": "CPU_ARCHITECTURE_X86_64",
"required_features": [
""
],
"dedicated_cores": false,
"isolate_smt_siblings": false
}

The DiskSpec object

DiskSpec describes one disk attached to a workload.

Attributes

  • disk_idstringRequired

    Identifier for this disk within the workload, e.g. "root" or "world-data". Must be unique within it.

  • sourceDiskSpec.SourceRequired
    Show child attributes
    • imagestringOne of source

      Boot from a platform or project image, e.g. projects/{project}/locations/{location}/images/{image}. The image is copied (or CoW-cloned where the node supports it) into a fresh disk.

    • volumestringOne of source

      Attach an existing persistent volume by resource name. The volume must be in the same location and unattached.

    • snapshotstringOne of source

      Restore from a snapshot resource name.

    • blankboolOne of source

      Create an empty, zero-filled disk of size_bytes.

  • size_bytesint64

    Size of the device. Required for a blank disk; for an image or snapshot source, zero means "the source's own size" and any larger value grows the filesystem on first boot.

  • DISK_TYPE_LOCAL_NVMEDISK_TYPE_NETWORK_SSDDISK_TYPE_NETWORK_SSD_HIGH_IOPS
  • read_onlybool

    Attach read-only. Several instances may share one read-only volume, which is how a common asset bundle is mounted into many game servers at once.

  • bootbool

    Marks the disk the workload boots from. Exactly one disk may set this.

  • delete_on_instance_deletebool

    Delete the underlying storage when the instance is deleted. Always true in effect for LOCAL_NVME.

  • Show child attributes
    • bandwidth_bytes_per_secondint64

      Sustained bytes/second. Zero means unlimited.

    • bandwidth_burst_bytesint64

      Burst allowance in bytes above the sustained rate.

    • iopsint64

      Sustained IO operations/second. Zero means unlimited.

    • iops_burstint64

      Burst allowance in operations above the sustained rate.

  • direct_iobool

    Use direct IO (O_DIRECT), bypassing the host page cache. Lowers memory pressure on the node and makes latency more predictable, at the cost of losing host-side caching.

DiskSpec
{
"disk_id": "my-disk",
"source": {
"image": ""
},
"size_bytes": "0",
"type": "DISK_TYPE_LOCAL_NVME",
"read_only": false,
"boot": false,
"delete_on_instance_delete": false,
"io_limits": {
"bandwidth_bytes_per_second": "0",
"bandwidth_burst_bytes": "0",
"iops": "0",
"iops_burst": "0"
},
"direct_io": false
}

The DiskSpec.IoLimits object

IoLimits caps the disk's throughput.

Attributes

  • bandwidth_bytes_per_secondint64

    Sustained bytes/second. Zero means unlimited.

  • bandwidth_burst_bytesint64

    Burst allowance in bytes above the sustained rate.

  • iopsint64

    Sustained IO operations/second. Zero means unlimited.

  • iops_burstint64

    Burst allowance in operations above the sustained rate.

DiskSpec.IoLimits
{
"bandwidth_bytes_per_second": "0",
"bandwidth_burst_bytes": "0",
"iops": "0",
"iops_burst": "0"
}

The DiskSpec.Source object

Source of the disk's initial contents.

Attributes

  • imagestringOne of source

    Boot from a platform or project image, e.g. projects/{project}/locations/{location}/images/{image}. The image is copied (or CoW-cloned where the node supports it) into a fresh disk.

  • volumestringOne of source

    Attach an existing persistent volume by resource name. The volume must be in the same location and unattached.

  • snapshotstringOne of source

    Restore from a snapshot resource name.

  • blankboolOne of source

    Create an empty, zero-filled disk of size_bytes.

DiskSpec.Source
{
"image": ""
}

The MemorySpec object

MemorySpec describes the RAM a workload needs.

Attributes

  • size_bytesint64Required

    Memory the workload sees, in bytes. Required.

  • reserved_bytesint64

    Memory guaranteed to the workload, in bytes. Must be no more than size_bytes. Zero means all of size_bytes is guaranteed.

    Reserving less than size_bytes requires balloon_enabled, so unused memory can be reclaimed when it is needed elsewhere.

  • balloon_enabledbool

    Allow memory the workload is not using to be reclaimed. Required when reserved_bytes is less than size_bytes.

  • hugepagesbool

    Back the workload's memory with 2 MiB pages. Noticeably faster for memory-heavy servers — large voxel worlds, big entity counts — but can only be placed where such memory is available.

  • hotplug_max_bytesint64

    Allow memory to grow to this size while running, without a restart. Zero disables it. Must be at least size_bytes when set.

  • sharedbool

    Allow identical memory pages to be shared with other workloads on the same machine. Saves memory when many servers run the same game, at some CPU cost and with weaker isolation between them.

MemorySpec
{
"size_bytes": "0",
"reserved_bytes": "0",
"balloon_enabled": false,
"hugepages": false,
"hotplug_max_bytes": "0",
"shared": false
}

The NetworkInterfaceSpec object

NetworkInterfaceSpec describes one network interface attached to a workload.

Attributes

  • interface_idstringRequired

    Stable identifier within the instance, e.g. "eth0".

  • networkstring

    Private network to attach to, as a resource name. Empty means the project's default network in this location.

  • private_ipv4string

    Requested private IPv4 address. Empty allocates one from the subnet.

  • PUBLIC_ADDRESS_MODE_NONEPUBLIC_ADDRESS_MODE_SHARED_IPV4PUBLIC_ADDRESS_MODE_DEDICATED_IPV4PUBLIC_ADDRESS_MODE_IPV6
  • NETWORK_TIER_STANDARDNETWORK_TIER_PREMIUM
  • Show child attributes
    • ingress_bits_per_secondint64

      Sustained bits/second. Zero means unlimited.

    • egress_bits_per_secondint64
    • ingress_burst_bitsint64

      Burst allowance in bits above the sustained rate.

    • egress_burst_bitsint64
    • ingress_packets_per_secondint64

      Packets/second ceiling, which is what actually protects a node from a small-packet flood. Zero means unlimited.

    • egress_packets_per_secondint64
  • mac_addressstring

    The interface's MAC address. Empty generates one. Pinning it matters for game licences tied to a MAC.

  • multi_queuebool

    Enable multi-queue virtio-net with one queue pair per vCPU. Raises packet throughput for servers handling many concurrent clients.

  • tagsrepeated string

    Network tags, which firewall rules on this interface's network target.

    Per interface rather than per instance because a rule belongs to one network, and an instance with an interface on each of two networks is answerable to two sets of rules. Lowercase letters, digits and hyphens, up to 63 characters each.

  • deny_inboundbool

    Refuse every inbound connection on this interface, whatever the network's firewall rules say. Replies to connections the workload opened still arrive.

    For an interface that exists so a workload can reach a network rather than be reached on it — a sandbox connected to one of your networks, for example.

  • no_default_routebool

    Send no internet traffic and no DNS through this interface: only the network's own range is reached through it. Without this, a workload with two interfaces could send its internet traffic out of either.

NetworkInterfaceSpec
{
"interface_id": "my-interface",
"network": "",
"private_ipv4": "",
"public_address_mode": "PUBLIC_ADDRESS_MODE_NONE",
"tier": "NETWORK_TIER_STANDARD",
"rate_limits": {
"ingress_bits_per_second": "0",
"egress_bits_per_second": "0",
"ingress_burst_bits": "0",
"egress_burst_bits": "0",
"ingress_packets_per_second": "0",
"egress_packets_per_second": "0"
},
"mac_address": "",
"multi_queue": false,
"tags": [
""
],
"deny_inbound": false,
"no_default_route": false
}

The NetworkInterfaceSpec.RateLimits object

Rate limits applied in both directions by the agent.

Attributes

  • ingress_bits_per_secondint64

    Sustained bits/second. Zero means unlimited.

  • egress_bits_per_secondint64
  • ingress_burst_bitsint64

    Burst allowance in bits above the sustained rate.

  • egress_burst_bitsint64
  • ingress_packets_per_secondint64

    Packets/second ceiling, which is what actually protects a node from a small-packet flood. Zero means unlimited.

  • egress_packets_per_secondint64
NetworkInterfaceSpec.RateLimits
{
"ingress_bits_per_second": "0",
"egress_bits_per_second": "0",
"ingress_burst_bits": "0",
"egress_burst_bits": "0",
"ingress_packets_per_second": "0",
"egress_packets_per_second": "0"
}

The NodeSelectorRequirement object

NodeSelectorRequirement matches against the labels of the machines a workload can run on, with Kubernetes selector semantics.

Attributes

  • keystringRequired
  • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXISTOPERATOR_GREATER_THANOPERATOR_LESS_THAN
  • valuesrepeated string

    Values to match. Empty for EXISTS and DOES_NOT_EXIST; exactly one entry for GREATER_THAN and LESS_THAN.

NodeSelectorRequirement
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}

The PlacementSpec object

PlacementSpec constrains which nodes an instance may land on.

Everything here is optional. A caller that supplies none of it gets whatever node satisfies the CPU, memory and disk requirements at the lowest cost, which is the right answer for most workloads.

Attributes

  • zonesrepeated string

    Zones the instance may land in, as location ids ("eu-west-2a"). Empty means any zone in the region. More than one entry is a preference list in priority order, not a hard set.

  • required_node_selectorsrepeated NodeSelectorRequirement

    Hard node requirements. A node must satisfy every entry.

    Show child attributes
    • keystringRequired
    • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXISTOPERATOR_GREATER_THANOPERATOR_LESS_THAN
    • valuesrepeated string

      Values to match. Empty for EXISTS and DOES_NOT_EXIST; exactly one entry for GREATER_THAN and LESS_THAN.

  • preferred_node_selectorsrepeated NodeSelectorRequirement

    Soft node preferences. Nodes satisfying more of these score higher, but none of them can make placement fail.

    Show child attributes
    • keystringRequired
    • OPERATOR_INOPERATOR_NOT_INOPERATOR_EXISTSOPERATOR_DOES_NOT_EXISTOPERATOR_GREATER_THANOPERATOR_LESS_THAN
    • valuesrepeated string

      Values to match. Empty for EXISTS and DOES_NOT_EXIST; exactly one entry for GREATER_THAN and LESS_THAN.

  • placement_groupstring

    Group this workload belongs to, scoped to the project. Workloads sharing a group are spread out or packed together according to policy.

  • PLACEMENT_POLICY_PACKPLACEMENT_POLICY_SPREADPLACEMENT_POLICY_STRICT_SPREAD_NODEPLACEMENT_POLICY_STRICT_SPREAD_ZONE
  • capacity_classstring

    Class of capacity to draw from. Leave empty to let Plany choose, which is right for almost every workload.

  • disallow_preemptiblebool

    Refuse to place onto pre-emptible (spot) capacity. Spot is materially cheaper and fine for a dev server, but wrong for a ranked match in progress.

  • nodestring

    Pin to one node by resource name. Bypasses scoring entirely; intended for debugging and for rescheduling a VM back onto the node holding its local disk.

PlacementSpec
{
"zones": [
""
],
"required_node_selectors": [
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}
],
"preferred_node_selectors": [
{
"key": "",
"operator": "OPERATOR_IN",
"values": [
""
]
}
],
"placement_group": "",
"policy": "PLACEMENT_POLICY_PACK",
"capacity_class": "",
"disallow_preemptible": false,
"node": ""
}

The SchedulingSpec object

SchedulingSpec governs an instance's lifecycle once it is placed: how long it may run, what happens when it goes quiet, and how it reacts to node loss.

Attributes

  • ON_HOST_MAINTENANCE_MIGRATEON_HOST_MAINTENANCE_TERMINATE
  • RESTART_POLICY_NEVERRESTART_POLICY_ALWAYSRESTART_POLICY_ON_FAILURE
  • preemptiblebool

    Run as spot: on spare capacity, at the spot rate, reclaimable with two minutes' notice when an on-demand workload needs the room.

  • preemption_noticeDuration

    Warning given before a spot reclaim, readable at /metadata/spot/instance-action on the metadata service. The notice is always two minutes; leave this unset.

  • max_run_durationDuration

    Stop the instance automatically once it has run this long. Zero means no limit. This is the guard rail that stops a forgotten dev server draining a hobby account's credit overnight.

  • termination_grace_periodDuration

    Time between the shutdown signal and a forced stop, so a game server can save its world. Zero uses the default of thirty seconds.

  • preemptible_fallbackbool

    With preemptible: place as an ordinary on-demand workload when no spare capacity fits, rather than waiting for some. The allocation says which happened, and it is what the instance is billed at.

SchedulingSpec
{
"on_host_maintenance": "ON_HOST_MAINTENANCE_MIGRATE",
"restart_policy": "RESTART_POLICY_NEVER",
"preemptible": false,
"preemption_notice": "300s",
"max_run_duration": "300s",
"termination_grace_period": "300s",
"preemptible_fallback": false
}

Build

Build is a set of artifacts. Bytes, and where to get them.

Modelled on the observation that almost nobody wants to upload a zip. Most game servers are already published somewhere — Steam, a vendor CDN — and making customers mirror those into Plany would be work with no benefit and a licensing question attached. So a build declares a source, and only the UPLOAD source stores bytes here at all.

  • display_namestringRequired
  • kindKindRequired

    What the artifacts are: a dedicated server, or a playable client.

    Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

    KIND_SERVERKIND_CLIENT
  • sourceBuildSourceRequired
    Show child attributes
    • uploadUploadSourceOne of source
      Show child attributes
      • upload_urlstringOutput only

        Where the client PUTs the archive. Output-only and short-lived; call GetBuildUploadUrl for a fresh one.

      • upload_url_expire_timeTimestampOutput only
      • objectstringOutput only

        Storage path once uploaded.

      • checksum_sha256string

        Hex SHA-256 of the archive, checked on arrival.

        Optional, and worth setting: given at presign time it is signed into the URL, so storage itself refuses an archive that does not hash to it. A corrupted upload never lands, which is stronger than comparing afterwards — there is no window in which a bad object exists and nothing to unwind.

    • steam_cmdSteamCmdSourceOne of source
      Show child attributes
      • app_idint64Required
      • branchstring

        Non-default branch, e.g. "prerelease". Empty takes the public branch.

      • branch_passwordstringInput only

        Password for a private branch. Write-only: it is stored encrypted and never returned.

      • usernamestring

        Steam account for downloads that refuse anonymous access. Empty uses anonymous, which covers most dedicated servers and almost no game clients — a client build is usually somebody's own licensed copy.

      • passwordstringInput only

        Write-only, stored encrypted.

      • validatebool

        Validate the install after download. Slower, and worth it on a build that will be copied to many machines.

    • archiveArchiveSourceOne of source
      Show child attributes
      • urlstringRequired
      • checksum_sha256string

        Hex SHA-256 of the download. Optional, and the difference between "this is the build I tested" and "this is whatever is at that URL today".

      • extractbool

        Unpack the download. False leaves it in place, which is what a bare server.jar wants.

      • headersmap<string, string>Input only

        Extra headers, for a vendor that requires a token. Write-only.

    • container_imageContainerImageSourceOne of source
      Show child attributes
      • imagestringRequired

        The reference as written, e.g. eu-west-2.plany.cr/my-project/lobby:1.4 or us-docker.pkg.dev/agones-images/examples/simple-game-server:0.35.

        A reference that already names a digest is taken as it is.

      • digeststringOutput only

        sha256:…, resolved when the build was created.

    • install_commandsrepeated string

      Commands run after the artifacts are in place, in order.

      The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

  • namestringIdentifier

    accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

    Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

    The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

  • versionstring

    Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

  • stateBuild.StateOutput only
    STATE_PENDING_UPLOADSTATE_PROCESSINGSTATE_READYSTATE_FAILEDSTATE_DELETED
  • errorStatusOutput only

    Why the build failed, when it did.

  • size_bytesint64Output only

    Total artifact size once resolved. Zero until known — a SteamCMD build does not know its size until an agent has run the download.

  • operating_systemOperatingSystem

    Operating system the build's artifacts target.

    OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
  • labelsmap<string, string>
  • systemboolOutput only

    Set on Plany-published builds, which you may read and use but not modify.

  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • etagstringOutput only

Game

Game is a catalogue entry, and a node in a tree.

Games contain games. Minecraft is a game; Java Edition is a game inside it; Forge is a game inside that; Forge 1.20.4 is a game inside that. Each level is something someone would name, and only the leaves can actually be run.

The tree is a flat collection with a parent pointer rather than nested resource names, because its depth is not known in advance. Two collections share this type:

games/{game} published by Plany, visible to everyone accounts/{account}/games/{game} your own

Your game may name a Plany game as its parent, which is how "our modpack, on top of Minecraft Forge" is expressed without copying anything.

One node, two halves

A game has a server half — what a game server runs — and a client half, the playable game. Either may be absent. Both inherit down the tree independently and field by field: a modpack that changes only the server's launch command keeps everything else its parent declared.

  • display_namestringRequired
  • namestringIdentifier

    games/{game} or accounts/{account}/games/{game}.

  • descriptionstring
  • parentstring

    The game this one refines. Empty for a root such as "Minecraft".

    A game may descend from a Plany-published game even when it is a customer's own — that is the point of the field.

  • versionstring

    Free-form version label for this node, e.g. "1.20.4".

  • How this game runs as a dedicated server. Deployed by plany.playpute.v1.

    Absent on a game nobody hosts — a single-player title a customer streams has no server half, and inventing an empty one would make every picker in Playpute offer a game it cannot run.

    Show child attributes
    • buildstring

      Artifacts the server runs. Must be a KIND_SERVER build.

    • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

      Show child attributes
      • launch_commandrepeated string

        Command that starts the server, run in the build's directory.

        Run directly with its arguments, not through a shell, so pipes, redirects and && have no special meaning. ${VAR} is substituted from environment first.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>
      • Files written before launch, e.g. server.properties, eula.txt.

      • Default size of a server running this game. A customer may ask for more.

      • startup_timeoutDuration

        How long to allow for start-up before declaring the server unhealthy.

        Generous by necessity: a modded Minecraft server can take minutes to generate a world on first boot, and killing it halfway leaves a corrupt save.

      • stop_signalstring

        Signal used to ask the server to exit, e.g. "SIGTERM".

      • stop_timeoutDuration

        Time allowed for a clean shutdown before the process is killed. Game servers write world state on exit; cutting that short loses player progress.

      • Settings a player-facing UI may expose, e.g. max players or difficulty.

      • operating_systemOperatingSystem

        Operating system the launch command expects.

        OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
      • max_playersint32

        How many players one server of this game holds.

        The game's own declaration, inherited down the catalogue like everything else here — Minecraft says twenty, and a Forge variant of it says twenty unless it says otherwise.

        It exists for autoscaling: "keep servers 70% full" needs a denominator, and there was nowhere on the platform that held one. Zero means unknown, and unknown is honoured rather than guessed — a group scaling on a percentage of an invented capacity would scale on a number the customer never gave. Such a group falls back to the terms that need no denominator: waiting connections, and CPU.

        Deliberately not read from the game's own settings — max-players in server.properties is a string a customer edits per server, and a fleet whose denominator changed per member would produce a different target for each of them.

      • sdk_healthSdkHealth

        How the platform decides a server has stopped answering, for a game that uses the Agones SDK's Health().

        Absent is off, and that is the right default rather than a gap: a game that never calls Health() would otherwise be declared unhealthy on a timer and replaced forever. Agones' defaults (5 seconds, 3 failures) are what the Autopilot importer writes when a manifest leaves health unset.

      • Overrides for a container build's entrypoint and arguments.

        Only meaningful with a ContainerImageSource build, where launch_command is not used: a container has an entrypoint and a command of its own, and Kubernetes' rule for overriding them is not "replace the whole argv". See ContainerRuntime.

  • How this game runs as a playable client. Absent on a game that declares no client.

    Show child attributes
    • buildstring

      Artifacts to install. Must be a KIND_CLIENT build.

    • launchrepeated string

      The command, as an argv, relative to the root of the unpacked build.

      Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

    • working_directorystring

      Working directory relative to the build root. Empty means the root.

    • environmentmap<string, string>

      Environment for the game, on top of the machine's own.

      Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

  • server_launchableboolOutput only

    Whether each half can actually be deployed, with inheritance applied.

    A branch node — "Minecraft", "Java Edition" — organises the tree and has no build behind it, so asking for a server of one is refused at the API rather than failing at boot.

    Two booleans rather than one, because the halves are independent: a game may be hostable without being playable from a client build, and the reverse.

  • client_launchableboolOutput only
  • systemboolOutput only

    Set on Plany-published games, which you may read and run but not modify.

  • labelsmap<string, string>
  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • etagstringOutput only

GetBuildDownloadUrlResponse

  • download_urlstring
  • expire_timeTimestamp
  • checksum_sha256string

    Hex SHA-256 of the archive, so the download can be verified rather than trusted.

GetBuildUploadUrlResponse

  • upload_urlstring
  • expire_timeTimestamp
  • required_headersmap<string, string>

    Headers the client must send with the PUT.

ListBuildsResponse

  • Show child attributes
    • display_namestringRequired
    • kindKindRequired

      What the artifacts are: a dedicated server, or a playable client.

      Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

      KIND_SERVERKIND_CLIENT
    • sourceBuildSourceRequired
      Show child attributes
      • uploadUploadSourceOne of source
      • steam_cmdSteamCmdSourceOne of source
      • archiveArchiveSourceOne of source
      • container_imageContainerImageSourceOne of source
      • install_commandsrepeated string

        Commands run after the artifacts are in place, in order.

        The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

    • namestringIdentifier

      accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

      Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

      The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

    • versionstring

      Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

    • stateBuild.StateOutput only
      STATE_PENDING_UPLOADSTATE_PROCESSINGSTATE_READYSTATE_FAILEDSTATE_DELETED
    • errorStatusOutput only

      Why the build failed, when it did.

    • size_bytesint64Output only

      Total artifact size once resolved. Zero until known — a SteamCMD build does not know its size until an agent has run the download.

    • operating_systemOperatingSystem

      Operating system the build's artifacts target.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • labelsmap<string, string>
    • systemboolOutput only

      Set on Plany-published builds, which you may read and use but not modify.

    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • next_page_tokenstring

ListGamesResponse

  • Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      games/{game} or accounts/{account}/games/{game}.

    • descriptionstring
    • parentstring

      The game this one refines. Empty for a root such as "Minecraft".

      A game may descend from a Plany-published game even when it is a customer's own — that is the point of the field.

    • versionstring

      Free-form version label for this node, e.g. "1.20.4".

    • How this game runs as a dedicated server. Deployed by plany.playpute.v1.

      Absent on a game nobody hosts — a single-player title a customer streams has no server half, and inventing an empty one would make every picker in Playpute offer a game it cannot run.

      Show child attributes
      • buildstring

        Artifacts the server runs. Must be a KIND_SERVER build.

      • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

    • How this game runs as a playable client. Absent on a game that declares no client.

      Show child attributes
      • buildstring

        Artifacts to install. Must be a KIND_CLIENT build.

      • launchrepeated string

        The command, as an argv, relative to the root of the unpacked build.

        Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>

        Environment for the game, on top of the machine's own.

        Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

    • server_launchableboolOutput only

      Whether each half can actually be deployed, with inheritance applied.

      A branch node — "Minecraft", "Java Edition" — organises the tree and has no build behind it, so asking for a server of one is refused at the API rather than failing at boot.

      Two booleans rather than one, because the halves are independent: a game may be hostable without being playable from a client build, and the reverse.

    • client_launchableboolOutput only
    • systemboolOutput only

      Set on Plany-published games, which you may read and run but not modify.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • next_page_tokenstring

ResolveGameResponse

  • gameGame

    The game itself, unresolved, so a caller has its display name and version without a second read.

    Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      games/{game} or accounts/{account}/games/{game}.

    • descriptionstring
    • parentstring

      The game this one refines. Empty for a root such as "Minecraft".

      A game may descend from a Plany-published game even when it is a customer's own — that is the point of the field.

    • versionstring

      Free-form version label for this node, e.g. "1.20.4".

    • How this game runs as a dedicated server. Deployed by plany.playpute.v1.

      Absent on a game nobody hosts — a single-player title a customer streams has no server half, and inventing an empty one would make every picker in Playpute offer a game it cannot run.

      Show child attributes
      • buildstring

        Artifacts the server runs. Must be a KIND_SERVER build.

      • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

    • How this game runs as a playable client. Absent on a game that declares no client.

      Show child attributes
      • buildstring

        Artifacts to install. Must be a KIND_CLIENT build.

      • launchrepeated string

        The command, as an argv, relative to the root of the unpacked build.

        Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>

        Environment for the game, on top of the machine's own.

        Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

    • server_launchableboolOutput only

      Whether each half can actually be deployed, with inheritance applied.

      A branch node — "Minecraft", "Java Edition" — organises the tree and has no build behind it, so asking for a server of one is refused at the API rather than failing at boot.

      Two booleans rather than one, because the halves are independent: a game may be hostable without being playable from a client build, and the reverse.

    • client_launchableboolOutput only
    • systemboolOutput only

      Set on Plany-published games, which you may read and run but not modify.

    • labelsmap<string, string>
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • Both halves with inheritance applied. Either may be absent, which is what a branch node and a server-only game both look like.

    Show child attributes
    • buildstring

      Artifacts the server runs. Must be a KIND_SERVER build.

    • How to run it. Inherited from ancestors field by field — see ResolveGame on the service.

      Show child attributes
      • launch_commandrepeated string

        Command that starts the server, run in the build's directory.

        Run directly with its arguments, not through a shell, so pipes, redirects and && have no special meaning. ${VAR} is substituted from environment first.

      • working_directorystring

        Working directory relative to the build root. Empty means the root.

      • environmentmap<string, string>
      • Files written before launch, e.g. server.properties, eula.txt.

      • Default size of a server running this game. A customer may ask for more.

      • startup_timeoutDuration

        How long to allow for start-up before declaring the server unhealthy.

        Generous by necessity: a modded Minecraft server can take minutes to generate a world on first boot, and killing it halfway leaves a corrupt save.

      • stop_signalstring

        Signal used to ask the server to exit, e.g. "SIGTERM".

      • stop_timeoutDuration

        Time allowed for a clean shutdown before the process is killed. Game servers write world state on exit; cutting that short loses player progress.

      • Settings a player-facing UI may expose, e.g. max players or difficulty.

      • operating_systemOperatingSystem

        Operating system the launch command expects.

        OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
      • max_playersint32

        How many players one server of this game holds.

        The game's own declaration, inherited down the catalogue like everything else here — Minecraft says twenty, and a Forge variant of it says twenty unless it says otherwise.

        It exists for autoscaling: "keep servers 70% full" needs a denominator, and there was nowhere on the platform that held one. Zero means unknown, and unknown is honoured rather than guessed — a group scaling on a percentage of an invented capacity would scale on a number the customer never gave. Such a group falls back to the terms that need no denominator: waiting connections, and CPU.

        Deliberately not read from the game's own settings — max-players in server.properties is a string a customer edits per server, and a fleet whose denominator changed per member would produce a different target for each of them.

      • sdk_healthSdkHealth

        How the platform decides a server has stopped answering, for a game that uses the Agones SDK's Health().

        Absent is off, and that is the right default rather than a gap: a game that never calls Health() would otherwise be declared unhealthy on a timer and replaced forever. Agones' defaults (5 seconds, 3 failures) are what the Autopilot importer writes when a manifest leaves health unset.

      • Overrides for a container build's entrypoint and arguments.

        Only meaningful with a ContainerImageSource build, where launch_command is not used: a container has an entrypoint and a command of its own, and Kubernetes' rule for overriding them is not "replace the whole argv". See ContainerRuntime.

  • Show child attributes
    • buildstring

      Artifacts to install. Must be a KIND_CLIENT build.

    • launchrepeated string

      The command, as an argv, relative to the root of the unpacked build.

      Executed, never handed to a shell. A launch command through cmd /c would make quoting the customer's problem and a game path containing a space a support ticket — and it is the difference between running a program and running whatever a build's name expands to.

    • working_directorystring

      Working directory relative to the build root. Empty means the root.

    • environmentmap<string, string>

      Environment for the game, on top of the machine's own.

      Not a secret store. This is on a catalogue entry anybody who can read the game can read, and it reaches a process the customer controls — so a licence key belongs in Secrets Manager and a graphics setting belongs here.

  • server_buildBuild

    The builds each half resolved to, in full rather than by name, so you have everything you need from one call.

    Show child attributes
    • display_namestringRequired
    • kindKindRequired

      What the artifacts are: a dedicated server, or a playable client.

      Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

      KIND_SERVERKIND_CLIENT
    • sourceBuildSourceRequired
      Show child attributes
      • uploadUploadSourceOne of source
      • steam_cmdSteamCmdSourceOne of source
      • archiveArchiveSourceOne of source
      • container_imageContainerImageSourceOne of source
      • install_commandsrepeated string

        Commands run after the artifacts are in place, in order.

        The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

    • namestringIdentifier

      accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

      Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

      The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

    • versionstring

      Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

    • stateBuild.StateOutput only
      STATE_PENDING_UPLOADSTATE_PROCESSINGSTATE_READYSTATE_FAILEDSTATE_DELETED
    • errorStatusOutput only

      Why the build failed, when it did.

    • size_bytesint64Output only

      Total artifact size once resolved. Zero until known — a SteamCMD build does not know its size until an agent has run the download.

    • operating_systemOperatingSystem

      Operating system the build's artifacts target.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • labelsmap<string, string>
    • systemboolOutput only

      Set on Plany-published builds, which you may read and use but not modify.

    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • client_buildBuild
    Show child attributes
    • display_namestringRequired
    • kindKindRequired

      What the artifacts are: a dedicated server, or a playable client.

      Required, and immutable. It decides what can run the build: a game server runs only KIND_SERVER builds, and a client build on a game server would install and have nothing to start.

      KIND_SERVERKIND_CLIENT
    • sourceBuildSourceRequired
      Show child attributes
      • uploadUploadSourceOne of source
      • steam_cmdSteamCmdSourceOne of source
      • archiveArchiveSourceOne of source
      • container_imageContainerImageSourceOne of source
      • install_commandsrepeated string

        Commands run after the artifacts are in place, in order.

        The escape hatch that keeps the sources above simple. Forge, for instance, ships an installer rather than a server: fetch the installer with an archive source, then run it here. Without this, every such game would need its own source type.

    • namestringIdentifier

      accounts/{account}/builds/{build}, or builds/{build} for one Plany publishes.

      Account-scoped rather than project-scoped: a studio building one server binary expects to use it across every project, and forcing a copy per project would mean re-uploading gigabytes to change nothing.

      The Plany-published pattern is written down because it is what the seeded catalogue has always used. It was absent from the resource annotation for as long as Playpute owned this message, so every tool generated from the schema believed builds/minecraft-java-1-20-4 — a name in the API's own seed data — was malformed.

    • versionstring

      Free-form version label, e.g. "1.20.4" or "v1.2.5". Plany does not parse it: game versioning is not semver often enough to be worth pretending.

    • stateBuild.StateOutput only
      STATE_PENDING_UPLOADSTATE_PROCESSINGSTATE_READYSTATE_FAILEDSTATE_DELETED
    • errorStatusOutput only

      Why the build failed, when it did.

    • size_bytesint64Output only

      Total artifact size once resolved. Zero until known — a SteamCMD build does not know its size until an agent has run the download.

    • operating_systemOperatingSystem

      Operating system the build's artifacts target.

      OPERATING_SYSTEM_LINUXOPERATING_SYSTEM_WINDOWS
    • labelsmap<string, string>
    • systemboolOutput only

      Set on Plany-published builds, which you may read and use but not modify.

    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • inherited_fromrepeated string

    Ancestors consulted, nearest first. Returned so a console can show where a setting came from, which is the difference between a form a customer trusts and one they merely accept.

Enums

Build.State

ValueDescription
STATE_UNSPECIFIED
STATE_PENDING_UPLOADCreated, waiting for artifacts. Only UPLOAD builds sit here; every other source is resolvable the moment it is declared.
STATE_PROCESSINGArtifacts are being fetched, unpacked or verified.
STATE_READYUsable by a game.
STATE_FAILEDSomething went wrong. `error` says what.
STATE_DELETEDSuperseded or deleted. Retained so a server that still references it can explain itself rather than dangling.

GameSetting.Type

ValueDescription
TYPE_UNSPECIFIED
TYPE_STRING
TYPE_INT
TYPE_BOOL
TYPE_ENUM

Kind

Kind is which half of a game something belongs to.

One enum rather than two, used by Build.kind and by the listing filter that asks which games are deployable. A second declaration meaning the same thing is the fault pkg/skus and pkg/guestmeta were both written after: two names for one fact, and one of them eventually drifts.

ValueDescription
KIND_UNSPECIFIED
KIND_SERVERA dedicated server. Runs headless, listens on ports, and is what `plany.playpute.v1.GameServer` installs.
KIND_CLIENTA playable client: a build with a window and a person in front of it, rather than a dedicated server.

OperatingSystem

OperatingSystem is what a build's artifacts were compiled for.

ValueDescription
OPERATING_SYSTEM_UNSPECIFIED
OPERATING_SYSTEM_LINUX
OPERATING_SYSTEM_WINDOWS

PortMapping.Protocol

ValueDescription
PROTOCOL_UNSPECIFIED
PROTOCOL_TCP
PROTOCOL_UDP

CpuArchitecture

CpuArchitecture is the instruction set a workload requires.

ValueDescription
CPU_ARCHITECTURE_UNSPECIFIED
CPU_ARCHITECTURE_X86_64
CPU_ARCHITECTURE_ARM64

DiskType

DiskType selects the class of backing storage, which determines both the performance envelope and the price.

ValueDescription
DISK_TYPE_UNSPECIFIED
DISK_TYPE_LOCAL_NVMENode-local NVMe. Fastest and cheapest, but the data is gone when the VM moves or the node is reclaimed. Correct for game server working data that is restored from object storage on boot.
DISK_TYPE_NETWORK_SSDNetwork-attached block storage (EBS gp3 class). Survives node loss and follows the VM when it is rescheduled.
DISK_TYPE_NETWORK_SSD_HIGH_IOPSHigh-IOPS network block storage (EBS io2 class). For databases and write-heavy persistence layers.

NetworkInterfaceSpec.PublicAddressMode

How the interface obtains a publicly routable address.

ValueDescription
PUBLIC_ADDRESS_MODE_UNSPECIFIED
PUBLIC_ADDRESS_MODE_NONENo public address. Reachable only inside the project's private network.
PUBLIC_ADDRESS_MODE_SHARED_IPV4A public IPv4 address shared with other workloads, with a dedicated range of ports forwarded to this one. Reachable ports without using a whole address.
PUBLIC_ADDRESS_MODE_DEDICATED_IPV4An IPv4 address used by this instance alone.
PUBLIC_ADDRESS_MODE_IPV6A routable IPv6 address from the node's delegated prefix.

NetworkTier

NetworkTier selects the egress path and its price.

ValueDescription
NETWORK_TIER_UNSPECIFIED
NETWORK_TIER_STANDARDStandard shared egress. Cheapest, best-effort.
NETWORK_TIER_PREMIUMPremium egress with DDoS scrubbing and anycast ingress. The default for public-facing game servers.

NodeSelectorRequirement.Operator

ValueDescription
OPERATOR_UNSPECIFIED
OPERATOR_IN
OPERATOR_NOT_IN
OPERATOR_EXISTS
OPERATOR_DOES_NOT_EXIST
OPERATOR_GREATER_THANNumeric comparison against the label's value, for labels such as `node.plany.cloud/cpu-ghz`.
OPERATOR_LESS_THAN

PlacementPolicy

PlacementPolicy expresses how instances of one logical group spread over failure domains.

ValueDescription
PLACEMENT_POLICY_UNSPECIFIED
PLACEMENT_POLICY_PACKPrefer nodes and zones that already hold members of the group. Packing raises utilisation and lets burst nodes drain back to zero sooner.
PLACEMENT_POLICY_SPREADPrefer nodes and zones holding no members of the group. Costs utilisation but means one node or zone failure cannot take out a whole fleet.
PLACEMENT_POLICY_STRICT_SPREAD_NODEHard requirement that no two members share a node.
PLACEMENT_POLICY_STRICT_SPREAD_ZONEHard requirement that no two members share a zone.

SchedulingSpec.OnHostMaintenance

What to do when the host must reclaim the instance.

ValueDescription
ON_HOST_MAINTENANCE_UNSPECIFIED
ON_HOST_MAINTENANCE_MIGRATELive-migrate to another node. Preserves the session at the cost of a brief stall during the final memory copy.
ON_HOST_MAINTENANCE_TERMINATETerminate. Correct for stateless workloads that are cheaper to restart than to move.

SchedulingSpec.RestartPolicy

What to do when the workload stops unexpectedly.

ValueDescription
RESTART_POLICY_UNSPECIFIED
RESTART_POLICY_NEVERNever restart automatically.
RESTART_POLICY_ALWAYSRestart on any exit, clean or not.
RESTART_POLICY_ON_FAILURERestart only after a non-zero exit or a failure of the machine it runs on. A clean shutdown is treated as intentional.