Skip to main content

Overview

Lifecycle methods control the state transitions of your game server within the Agones system. These methods are part of the stable SDK service (agones.dev.sdk.SDK).

State Diagram

┌─────────────┐
│   Starting  │
└──────┬──────┘

       │ Container starts

┌─────────────┐
│ Scheduled   │
└──────┬──────┘

       │ Pod scheduled

┌─────────────┐     Ready()     ┌─────────────┐
│ RequestReady│ ───────────────▶│    Ready    │
└─────────────┘                 └──────┬──────┘

                                       │ Allocated via API
                                       │ or Allocate()

                                ┌─────────────┐
                                │  Allocated  │
                                └──────┬──────┘

                                       │ Shutdown()

                                ┌─────────────┐
                                │  Shutdown   │
                                └─────────────┘

Ready

Signals that the game server is ready to accept player connections and can be allocated.
rpc Ready (Empty) returns (Empty);

When to Call

Call Ready() when your game server has:
  • Loaded all required assets and configurations
  • Initialized networking and listening on game ports
  • Completed any warm-up or pre-caching operations
  • Is ready to accept player connections immediately after allocation

Behavior

Transitions the game server from RequestReady state to Ready state, making it available for allocation via the Allocation API or Fleet autoscaling.

Request

-
Empty
No parameters required.

Response

-
Empty
Returns empty on success.

Example Usage

import (
    "log"
    "agones.dev/agones/sdks/go"
)

s, err := sdk.NewSDK()
if err != nil {
    log.Fatalf("Could not connect to sdk: %v", err)
}

// Load assets, initialize game state, etc.
loadGameAssets()
initializeNetworking()

// Signal readiness
if err := s.Ready(); err != nil {
    log.Fatalf("Could not send ready message: %v", err)
}

log.Println("Game server is ready for allocation")

Allocate

Performs self-allocation, moving the game server to the Allocated state without going through the Allocation API.
rpc Allocate(Empty) returns (Empty);

When to Call

Use self-allocation when:
  • Implementing custom matchmaking within the game server
  • Testing allocation behavior
  • Creating lobby servers that self-allocate when players join
Most deployments should use the Allocation API instead of self-allocation. Self-allocation bypasses scheduling strategies and allocation policies.

Behavior

Transitions the game server from Ready state to Allocated state. The server will not be allocated by the Allocation API after this call.

Request

-
Empty
No parameters required.

Response

-
Empty
Returns empty on success.

Example Usage

// Self-allocate when first player connects
func onFirstPlayerConnect() {
    if err := sdk.Allocate(); err != nil {
        log.Printf("Could not allocate: %v", err)
        return
    }
    log.Println("Game server self-allocated")
}

Shutdown

Signals that the game server is shutting down and should be terminated. This releases the game server resources back to the cluster.
rpc Shutdown (Empty) returns (Empty);

When to Call

Call Shutdown() when:
  • A game match has completed
  • All players have disconnected
  • A fatal error occurs that prevents normal operation
  • The server has been idle for too long (custom logic)

Behavior

Transitions the game server to Shutdown state. Kubernetes will then terminate the Pod, typically within 30 seconds (grace period).

Request

-
Empty
No parameters required.

Response

-
Empty
Returns empty on success.

Example Usage

// Shutdown when match ends
func onMatchEnd() {
    log.Println("Match ended, shutting down...")
    
    // Clean up resources
    saveMatchResults()
    disconnectPlayers()
    
    // Signal shutdown
    if err := sdk.Shutdown(); err != nil {
        log.Printf("Could not shutdown: %v", err)
    }
    
    // Give time for SDK call to complete
    time.Sleep(2 * time.Second)
    os.Exit(0)
}

Reserve

Marks the game server as reserved for a specific duration, preventing it from being allocated by the Allocation API.
rpc Reserve(Duration) returns (Empty);

When to Call

Use reservations for:
  • Holding a server during matchmaking while finalizing player selection
  • Implementing custom allocation logic with time-bounded holds
  • Creating lobbies that need temporary protection from allocation

Behavior

Transitions the game server to Reserved state for the specified duration. After the duration expires, the server returns to Ready state automatically.
Reservations can be extended by calling Reserve() again before expiration. Each call resets the timer.

Request

seconds
int64
required
Duration in seconds to reserve the game server. Must be a positive integer.

Response

-
Empty
Returns empty on success.

Example Usage

import "time"

// Reserve for 30 seconds during matchmaking
func reserveForMatchmaking() error {
    duration := &sdk.Duration{
        Seconds: 30,
    }
    
    if err := sdk.Reserve(duration); err != nil {
        return fmt.Errorf("could not reserve: %v", err)
    }
    
    log.Println("Game server reserved for 30 seconds")
    return nil
}

// Extend reservation if matchmaking takes longer
func extendReservation() error {
    duration := &sdk.Duration{
        Seconds: 30,
    }
    return sdk.Reserve(duration)
}

GetGameServer

Retrieves the current state of the game server.
rpc GetGameServer (Empty) returns (GameServer);

When to Call

Retrieve game server state to:
  • Check current metadata (labels, annotations)
  • Read configuration from spec
  • Inspect current status (state, ports, addresses)
  • Access player tracking or counter/list data

Request

-
Empty
No parameters required.

Response

object_meta
ObjectMeta
Kubernetes object metadata.
spec
Spec
Game server specification.
status
Status
Current game server status.

Example Usage

gs, err := sdk.GameServer()
if err != nil {
    log.Printf("Could not get game server: %v", err)
    return
}

log.Printf("Game server name: %s", gs.ObjectMeta.Name)
log.Printf("Current state: %s", gs.Status.State)
log.Printf("Address: %s", gs.Status.Address)

for _, port := range gs.Status.Ports {
    log.Printf("Port %s: %d", port.Name, port.Port)
}

WatchGameServer

Streams game server updates whenever the game server resource changes.
rpc WatchGameServer (Empty) returns (stream GameServer);

When to Call

Use watch to:
  • React to state changes (e.g., allocation)
  • Monitor metadata updates from external sources
  • Track counter and list changes made via the Allocation API
  • Implement event-driven game server logic

Behavior

Opens a server-streaming connection that sends a GameServer message whenever the game server resource is updated in Kubernetes.

Request

-
Empty
No parameters required.

Response

stream
GameServer
Stream of game server updates. Each message contains the full game server state (same structure as GetGameServer).

Example Usage

ctx := context.Background()
stream, err := sdk.WatchGameServer(ctx)
if err != nil {
    log.Fatalf("Could not watch game server: %v", err)
}

for {
    gs, err := stream.Recv()
    if err != nil {
        log.Printf("Watch stream error: %v", err)
        break
    }
    
    log.Printf("Game server updated - State: %s", gs.Status.State)
    
    // React to state changes
    if gs.Status.State == "Allocated" {
        log.Println("Server was allocated, starting match...")
        startMatch()
    }
}

HTTP Gateway

All lifecycle methods are available via HTTP/JSON:
curl -X POST http://localhost:9357/ready -d '{}'

Build docs developers (and LLMs) love