Migration Guide

Agones to Gameye migration guide

Your game server already runs in a container. Moving to Gameye means removing the Agones SDK calls, swapping GameServerAllocation for one API call, and handing the clusters, fleets and autoscalers to Gameye.

Same container No SDK No Kubernetes 6 steps
📦

Built for Agones? Your image is the starting point.

Agones runs each game server as a container in a Kubernetes Pod. Gameye runs each match as one Linux container. The server build inside the image stays. The code change is taking out the Agones SDK.

Jump to the migration steps →

Agones is an open-source project that adds game server resources to Kubernetes: GameServer, Fleet, GameServerAllocation and FleetAutoscaler. It is a sound choice for studios that want to run their own clusters. Running it means you also own the clusters, the node pools in every region, the Agones and Kubernetes upgrades, and the on-call rota.

On Gameye you keep the game server and the matchmaker. You stop operating the layer underneath them. If you are still deciding whether to self-host, read Run Agones yourself or use managed hosting? first.

What changes
  • Agones SDK calls (Ready, Health, Shutdown, and Allocate if you use it) come out of the server
  • GameServerAllocation becomes POST /session
  • GameServer port specs become ports on a Gameye application
  • Your image goes to Docker Hub or GitHub Container Registry, with a new tag per build
  • Fleets, FleetAutoscalers and clusters are no longer yours to run
What stays the same
  • Your dedicated server build and netcode
  • Your matchmaker and its rules
  • Clients still receive an IP and port
  • Match config passed as args or environment variables
  • SIGTERM handling for a clean shutdown

Where does the cost difference come from?

Agones is free software. The bill comes from what it runs on and who runs it. These are the lines that go away or change when you move.

Idle nodes

A Fleet keeps Ready game servers waiting on nodes you pay for, and a Buffer policy keeps that headroom on purpose. On Gameye you start a session when a match forms, and billing stops when the container exits.

Cloud egress

On a managed Kubernetes service, outbound game traffic is billed by your cloud provider per gigabyte. Gameye includes bandwidth in its published pricing.

Cluster engineering

Each Agones release supports three Kubernetes versions, so cluster upgrades and Agones upgrades are planned together, in every region you run. Someone also owns autoscaler tuning, allocation services and on-call. On Gameye none of that sits with your team.

Regions

Adding a region on Agones means another cluster with its own node pools and allocation endpoint. On Gameye a region is a location value in the session request.

For a worked cost comparison of self-run Agones and Gameye, see the Gameye vs Agones cost breakdown. For current rates, see Gameye pricing. Agones facts on this page were checked against agones.dev on .


What does the migration path look like?

1
Push your image where Gameye can pull it

Gameye pulls images from Docker Hub or GitHub Container Registry. Push the same Linux x86-64 server image you deploy to Agones, create a Gameye application for it, and give Gameye read access. Gameye does not host a registry, so you keep using your own.

Use a new tag for every build, such as a build number or commit SHA. Nodes that already have a tag do not download it again, so re-pushing latest will not deliver a new build.

Getting started in Gameye Docs →

2
Remove the Agones SDK calls

On Agones, your server talks to the SDK server that runs alongside it in the Pod. Take those calls out:

  • SDK.Ready(): remove. A Gameye session is running once POST /session returns.
  • SDK.Health() ping loop: remove. Gameye does not expect health pings.
  • SDK.Shutdown(): replace with a normal process exit. When the server process exits, the session ends and billing stops.
  • SDK.Allocate(), if your server self-allocates: remove. Your backend starts the session instead.

Keep your SIGTERM handler. When your backend calls DELETE /session/{id} or a session's ttl runs out, Gameye sends SIGTERM, then SIGKILL if the process is still running 50 seconds later. Save results and logs in that window, then exit.

The engine guides show the shutdown path for each engine: Unreal, Unity and Godot.

3
Declare your ports on the application

The ports list in your GameServer spec becomes the ports on your Gameye application: a protocol and a container port, for example UDP 7777.

  • Bridge networking (the default) is closest to the Agones Dynamic port policy. Your server listens on a fixed container port and Gameye maps it to a free host port.
  • Host networking is closest to Passthrough. Your server reads its assigned port at startup from a variable such as GAMEYE_PORT_UDP_7777 and listens on it.

Gameye sets the port variables in both modes, along with GAMEYE_IP, GAMEYE_REGION and GAMEYE_CONTAINER, so a server that advertises its own address can still do so.

Container environment variables →

4
Replace GameServerAllocation with POST /session

Wherever your backend or matchmaker creates a GameServerAllocation, it calls the Gameye API instead. The response carries the address and ports, like the allocation status does.

Before (Agones)
apiVersion: allocation.agones.dev/v1
kind: GameServerAllocation
spec:
  selectors:
    - matchLabels:
        agones.dev/fleet: my-fleet
# status: state Allocated, gameServerName, address, ports
After (Gameye)
POST /session
{ "image": "my-game-server", "version": "build-142",
  "location": "europe", "env": { "MAX_PLAYERS": "16" },
  "labels": { "match": "m-8812" }, "ttl": "1h" }

201 Created
{ "id": "...", "host": "203.0.113.42",
  "ports": [{ "type": "udp", "container": 7777, "host": 49152 }] }

Match settings you put in GameServer labels, annotations or container args carry over to labels, env and args. Do not put secrets in env: the values are visible to anyone with Admin Panel access.

POST /session reference → · Custom matchmaker guide →

5
Pick regions per session

Instead of one cluster per region, you choose a region on each request. For a single-region game, pass a fixed location. For a global game, call GET /available-location/{image} to get the regions where your image is available and an IP for each, have clients ping those IPs, and start the session in the region with the best result for the match.

Region selection guide →

6
Track players, then move traffic

If you count connected players, report them from your backend with PUT /session/player/join and DELETE /session/player/leave, each taking a session ID and a players list.

Then run both platforms side by side. Send one region's matches to Gameye, compare session start, server behaviour and cost, and move the rest region by region. Your Agones clusters keep serving everything else until you switch them off.

Player join reference →

✓

What stays the same: your server logic, netcode, client connection flow and matchmaking rules. The migration touches the SDK calls, the allocation call and where the image lives.


How do Agones concepts map to Gameye?

Agones Gameye
GameServerSession: one running container, started by POST /session
FleetApplication and image tag. No pool of Ready servers to size
FleetAutoscalerNone. Gameye places each session on bare metal first and uses cloud capacity when a region's bare metal is full
GameServerAllocationPOST /session, which returns host and ports
SDK.Ready()Not needed
SDK.Health()Not needed
SDK.Shutdown()Process exit, or DELETE /session/{id} from your backend
SDK server in the PodNone. Nothing runs next to your server
Port policy DynamicBridge networking (default)
Port policy PassthroughHost networking with GAMEYE_PORT_* variables
GameServer labels and annotationslabels and env on POST /session
Counting players through the SDKPUT /session/player/join and DELETE /session/player/leave
One cluster per regionlocation per session, chosen with GET /available-location/{image}
Kubernetes and Agones upgradesNone on your side

What does your team stop running?

Clusters and node pools

No Kubernetes clusters, node pools or Agones controllers per region. Gameye runs the machines and the orchestration.

Version upgrades

Each Agones release supports three Kubernetes versions, so the two upgrade cycles are linked. With no SDK in your server, there is no SDK version to keep in step either.

Autoscaler tuning

No buffer sizes, webhook policies or schedules to tune. You start a session per match and Gameye places it.

Allocation services

No allocator endpoint per cluster and no multi-cluster routing. Your backend makes one HTTP call to one API.

Your matchmaker stays

Gameye Docs have guides for Nakama, AWS FlexMatch, Unity Matchmaker, PlayFab, Photon Fusion, Colyseus and custom matchmakers.

Agent-ready

The open-source gameye-mcp server and gameye-skills let a coding agent containerize a Unity, Unreal, Godot or Node.js server and start and stop sessions and read their logs through the Gameye API.


Frequently asked questions

Can I reuse my Agones game server image on Gameye?

Yes. Gameye runs your dedicated server as a Linux container, so the image you built for Agones is the starting point. Remove the Agones SDK calls, push the image to Docker Hub or GitHub Container Registry with a new tag, and register the game port on a Gameye application. Getting started →

What replaces the Agones SDK on Gameye?

Nothing. Gameye needs no SDK, sidecar or plugin in your server. Your server does not call Ready or send Health pings. The session ends when your server process exits, and billing stops when the container exits. If Gameye stops the session, through DELETE /session or a ttl, it sends SIGTERM and then SIGKILL 50 seconds later.

What replaces GameServerAllocation?

One HTTP call. When your matchmaker forms a match, your backend calls POST /session with the application name (image), a location and optionally a version tag, args, env, labels and a ttl. The 201 response contains the host IP and a ports array that maps each container port to its host port. Your backend sends that IP and port to the players.

Do I still need Fleets and FleetAutoscalers on Gameye?

No. There is no fleet to size and no autoscaler policy to tune. You start one session per match through the API. Gameye places sessions on bare metal first and uses cloud capacity when bare metal in that region is full.

Do I keep my matchmaker when I move off Agones?

Yes. Whatever calls the Agones allocator today calls POST /session instead. Gameye Docs have integration guides for Nakama, AWS FlexMatch, Unity Matchmaker, PlayFab, Photon Fusion, Colyseus and custom matchmakers.

How does my server find its port on Gameye?

Bridge networking is the default. Your server listens on a fixed container port, such as UDP 7777, and Gameye maps it to a free host port. With host networking, your server reads its port from an environment variable at startup, such as GAMEYE_PORT_UDP_7777. Gameye sets these port variables in both modes. Container environment variables →

Ready to move off Agones?

Start a Developer Trial, push your existing image with the SDK calls removed, and start your first session with one API call.