

# Preparing your games for hosting with Amazon GameLift Servers Realtime
<a name="realtime-integration-intro"></a>

Get your multiplayer games ready for hosting with Amazon GameLift Servers Realtime. This section guides you through the steps required to create a hosting solution for your game using Realtime servers and Amazon GameLift Servers managed EC2 hosting in the cloud. 

Your solution will have the following components: 
+ A Realtime server that you customize to work with your game. This component is in the form of a script containing JavaScript code that provides your custom configuration and optional extensions. This script tells Amazon GameLift Servers how to set up and run Realtime servers for you. To use this script, you upload it to the Amazon GameLift Servers service.
+ A version of your game client that's been integrated with the AWS SDK and the Amazon GameLift Servers Realtime client SDK. Use these tools to add the necessary functionality to communicate with the Amazon GameLift Servers service to start or join game sessions, as well as connect to and interact with Realtime servers to play the game. 

**Topics**
+ [Customize an Amazon GameLift Servers Realtime script](realtime-script.md)
+ [Integrate a game client for Amazon GameLift Servers Realtime](realtime-client.md)
+ [Upload a script for Amazon GameLift Servers Realtime servers](realtime-script-uploading.md)
+ [Update an Amazon GameLift Servers Realtime script](realtime-script-uploading-update.md)

# Customize an Amazon GameLift Servers Realtime script
<a name="realtime-script"></a>

To use Amazon GameLift Servers Realtime servers for your game, you need to provide a script (in the form of JavaScript code) to configure and optionally customize how the Amazon GameLift Servers Realtime server run and interact with your game clients. When your script is ready, upload it to the Amazon GameLift Servers service (see [Upload a script for Amazon GameLift Servers Realtime servers](realtime-script-uploading.md)) and use it to create a fleet of game server hosts.

Start with the default Realtime script and configure it with the following functionality.

## Manage game session life-cycle (required)
<a name="realtime-script-init"></a>

At a minimum, a Realtime script must include the `Init()` function, which prepares the Realtime server to start a game session. It is also highly recommended that you also provide a way to terminate game sessions, to ensure that new game sessions can continue to be started on your fleet.

The `Init()` callback function, when called, is passed a Realtime session object, which contains an interface for the Realtime server. See [Amazon GameLift Servers Realtime interface](realtime-script-objects.md) for more details on this interface.

To gracefully end a game session, the script must also call the Realtime server's `session.processEnding` function. This requires some mechanism to determine when to end a session. The script example code illustrates a simple mechanism that checks for player connections and triggers game session termination when no players have been connected to the session for a specified length of time.

Amazon GameLift Servers Realtime with the most basic configuration--server process initialization and termination--essentially act as stateless relay servers. The Realtime server relays messages and game data between game clients that are connected to the game, but takes no independent action to process data or perform logic. You can optionally add game logic, triggered by game events or other mechanisms, as needed for your game.

## Add server-side game logic (optional)
<a name="realtime-script-logic"></a>

You can optionally add game logic to your Realtime script. For example, you might do any or all of the following. The script example code provides illustration. See [Script reference for Amazon GameLift Servers Realtime](realtime-script-ref.md). 
+ **Add event-driven logic.** Implement the callback functions to respond to client-server events. See [Script callbacks for Amazon GameLift Servers Realtime](realtime-script-callbacks.md) for a complete list of callbacks.
+ **Trigger logic by sending messages to the server.** Create a set of special operation codes for messages sent from game clients to the server, and add functions to handle receipt. Use the callback `onMessage`, and parse the message content using the `gameMessage` interface (see [gameMessage.opcode](realtime-script-objects.md#realtime-script-objects-gamemessageopcode)). 
+ Enable game logic to access your other AWS resources. For details, see [ Communicate with other AWS resources from your fleets](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-server-resources.html).
+ Allow game logic to access fleet information for the instance it is running on. For details, see [ Get fleet data for an Amazon GameLift Servers instance](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-server-fleetinfo.html).

## Node.js runtime versions
<a name="realtime-script-nodejs"></a>

Amazon GameLift Servers Realtime servers support multiple Node.js runtime versions. You can specify the Node.js version when creating a script. The supported versions are:
+ **Node.js 10** (Default) - Runs on Amazon Linux 2. Node.js 10 will reach end of support on September 30, 2026. See more details in the [Node.js 10 FAQs](https://aws.amazon.com/gamelift/faq/nodejs10/). For migration guidance, see [Migrating from Node.js 10 to 24](https://docs.aws.amazon.com/gamelift/latest/realtimeguide/realtime-script.html#realtime-script-nodejs-migration). 
+ **Node.js 24** (Recommended) - Runs on Amazon Linux 2023.

To specify the Node.js version and add optional customizations like install scripts, see [Upload a script for Amazon GameLift Servers Realtime servers](realtime-script-uploading.md).

## Migrating from Node.js 10 to 24
<a name="realtime-script-nodejs-migration"></a>

To migrate existing Amazon GameLift Servers Realtime servers from Node.js 10 to 24:

1. **Review your fleets** - Check if you have existing fleets from scripts running on Node.js 10. You can identify affected fleets using several methods:
   + In the Amazon GameLift Servers console, navigate to the AWS Health Dashboard, look for the Node.js 10 end of support notification, and choose the **Affected resources** tab to see a list of your fleets using scripts with Node.js 10 runtime.
   + In the Amazon GameLift Servers console, navigate to **Managed EC2 fleets** and look for fleets created from scripts with Node.js 10 runtime. You can also check the Node.js version in the details page of each script resource, as well as identify fleets created with each script.

1. **Create a new script** - Create and upload your existing script and choose the new target `NodeJsVersion` i.e., `24.x` for Node.js 24. If there are any errors uploading or starting your script, follow these steps:

   1. Review the changes between Amazon Linux 2 and Amazon Linux 2023. For more information on Amazon Linux 2023 and the architectural differences with Amazon Linux 2, see [ Comparing AL2 and AL2023](https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html).

   1. Review the changes between Node.js versions. For more information on Node.js version changes, see [Node.js release notes](https://nodejs.org/en/about/releases/).

   1. Update your script. Make required changes to your scripts to work with the new target Node.js version and operating system.

   1. Upload your new script. Upload your new script to Amazon GameLift Servers. For more information, see [Upload a script for Amazon GameLift Servers Realtime servers](realtime-script-uploading.md).

1. **Create a test fleet with the new script** - We recommend this step to ensure there are no errors in initializing your script and activating the fleet. For help with fleet creation issues, see [ Debug fleet creation issues](https://docs.aws.amazon.com/gameliftservers/latest/realtimeguide/fleets-creating-debug-realtime.html).

1. **Review fleet events for errors** - If there are errors during fleet creation, you can look for the error messages on the **Events** tab on the Fleets view page. For more information about fleet events, see [ Event](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_Event.html) in the API Reference.

1. **(Optional) Update your script** - If you encountered errors during script or fleet creation, fix and update your script until your fleet activates and the Amazon GameLift Servers Realtime server launches as expected. For troubleshooting guidance, see [Troubleshooting Amazon GameLift Servers issues](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/troubleshooting-intro.html).

1. **(Optional) Create test game sessions** - After your test fleet is active, set your game backend to target your new fleet. We recommend that you create test game sessions to verify game client connectivity.

1. **Migrate your player traffic to your new production fleet** - If you have a game in production serving live player traffic, you can use Amazon GameLift Servers Queues and Aliases to migrate players to your new Node.js 24 runtime fleets. Use aliases to transfer players to a new fleet. When sending game session requests to Amazon GameLift Servers, specify a fleet alias instead of a fleet ID. For more information, see [ Create an alias](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/aliases-creating.html).

For information about Node.js version support and end-of-life schedules, see the [Node.js releases](https://nodejs.org/en/about/releases/).

## Amazon GameLift Servers Realtime script example
<a name="realtime-script-examples"></a><a name="realtime-script-examples-custom"></a>

This example illustrates a basic script needed to deploy Amazon GameLift Servers Realtime plus some custom logic. It contains the required `Init()` function, and uses a timer mechanism to trigger game session termination based on length of time with no player connections. It also includes some hooks for custom logic, including some callback implementations. 

```
// Example Realtime Server Script
'use strict';

// Example override configuration
const configuration = {
    pingIntervalTime: 30000,
    maxPlayers: 32
};

// Timing mechanism used to trigger end of game session. Defines how long, in milliseconds, between each tick in the example tick loop
const tickTime = 1000;

// Defines how to long to wait in Seconds before beginning early termination check in the example tick loop
const minimumElapsedTime = 120;

var session;                        // The Realtime server session object
var logger;                         // Log at appropriate level via .info(), .warn(), .error(), .debug()
var startTime;                      // Records the time the process started
var activePlayers = 0;              // Records the number of connected players
var onProcessStartedCalled = false; // Record if onProcessStarted has been called

// Example custom op codes for user-defined messages
// Any positive op code number can be defined here. These should match your client code.
const OP_CODE_CUSTOM_OP1 = 111;
const OP_CODE_CUSTOM_OP1_REPLY = 112;
const OP_CODE_PLAYER_ACCEPTED = 113;
const OP_CODE_DISCONNECT_NOTIFICATION = 114;

// Example groups for user-defined groups
// Any positive group number can be defined here. These should match your client code.
// When referring to user-defined groups, "-1" represents all groups, "0" is reserved.
const RED_TEAM_GROUP = 1;
const BLUE_TEAM_GROUP = 2;

// Called when game server is initialized, passed server's object of current session
function init(rtSession) {
    session = rtSession;
    logger = session.getLogger();
}

// On Process Started is called when the process has begun and we need to perform any
// bootstrapping.  This is where the developer should insert any code to prepare
// the process to be able to host a game session, for example load some settings or set state
//
// Return true if the process has been appropriately prepared and it is okay to invoke the
// GameLift ProcessReady() call.
function onProcessStarted(args) {
    onProcessStartedCalled = true;
    logger.info("Starting process with args: " + args);
    logger.info("Ready to host games...");

    return true;
}

// Called when a new game session is started on the process
function onStartGameSession(gameSession) {
    // Complete any game session set-up

    // Set up an example tick loop to perform server initiated actions
    startTime = getTimeInS();
    tickLoop();
}

// Handle process termination if the process is being terminated by Amazon GameLift Servers
// You do not need to call ProcessEnding here
function onProcessTerminate() {
    // Perform any clean up
}

// Return true if the process is healthy
function onHealthCheck() {
    return true;
}

// On Player Connect is called when a player has passed initial validation
// Return true if player should connect, false to reject
function onPlayerConnect(connectMsg) {
    // Perform any validation needed for connectMsg.payload, connectMsg.peerId
    return true;
}

// Called when a Player is accepted into the game
function onPlayerAccepted(player) {
    // This player was accepted -- let's send them a message
    const msg = session.newTextGameMessage(OP_CODE_PLAYER_ACCEPTED, player.peerId,
                                             "Peer " + player.peerId + " accepted");
    session.sendReliableMessage(msg, player.peerId);
    activePlayers++;
}

// On Player Disconnect is called when a player has left or been forcibly terminated
// Is only called for players that actually connected to the server and not those rejected by validation
// This is called before the player is removed from the player list
function onPlayerDisconnect(peerId) {
    // send a message to each remaining player letting them know about the disconnect
    const outMessage = session.newTextGameMessage(OP_CODE_DISCONNECT_NOTIFICATION,
                                                session.getServerId(),
                                                "Peer " + peerId + " disconnected");
    session.getPlayers().forEach((player, playerId) => {
        if (playerId != peerId) {
            session.sendReliableMessage(outMessage, playerId);
        }
    });
    activePlayers--;
}

// Handle a message to the server
function onMessage(gameMessage) {
    switch (gameMessage.opCode) {
      case OP_CODE_CUSTOM_OP1: {
        // do operation 1 with gameMessage.payload for example sendToGroup
        const outMessage = session.newTextGameMessage(OP_CODE_CUSTOM_OP1_REPLY, session.getServerId(), gameMessage.payload);
        session.sendGroupMessage(outMessage, RED_TEAM_GROUP);
        break;
      }
    }
}

// Return true if the send should be allowed
function onSendToPlayer(gameMessage) {
    // This example rejects any payloads containing "Reject"
    return (!gameMessage.getPayloadAsText().includes("Reject"));
}

// Return true if the send to group should be allowed
// Use gameMessage.getPayloadAsText() to get the message contents
function onSendToGroup(gameMessage) {
    return true;
}

// Return true if the player is allowed to join the group
function onPlayerJoinGroup(groupId, peerId) {
    return true;
}

// Return true if the player is allowed to leave the group
function onPlayerLeaveGroup(groupId, peerId) {
    return true;
}

// A simple tick loop example
// Checks to see if a minimum amount of time has passed before seeing if the game has ended
async function tickLoop() {
    const elapsedTime = getTimeInS() - startTime;
    logger.info("Tick... " + elapsedTime + " activePlayers: " + activePlayers);

    // In Tick loop - see if all players have left early after a minimum period of time has passed
    // Call processEnding() to terminate the process and quit
    if ( (activePlayers == 0) && (elapsedTime > minimumElapsedTime)) {
        logger.info("All players disconnected. Ending game");
        const outcome = await session.processEnding();
        logger.info("Completed process ending with: " + outcome);
        process.exit(0);
    }
    else {
        setTimeout(tickLoop, tickTime);
    }
}

// Calculates the current time in seconds
function getTimeInS() {
    return Math.round(new Date().getTime()/1000);
}

exports.ssExports = {
    configuration: configuration,
    init: init,
    onProcessStarted: onProcessStarted,
    onMessage: onMessage,
    onPlayerConnect: onPlayerConnect,
    onPlayerAccepted: onPlayerAccepted,
    onPlayerDisconnect: onPlayerDisconnect,
    onSendToPlayer: onSendToPlayer,
    onSendToGroup: onSendToGroup,
    onPlayerJoinGroup: onPlayerJoinGroup,
    onPlayerLeaveGroup: onPlayerLeaveGroup,
    onStartGameSession: onStartGameSession,
    onProcessTerminate: onProcessTerminate,
    onHealthCheck: onHealthCheck
};
```

# Integrate a game client for Amazon GameLift Servers Realtime
<a name="realtime-client"></a>

When using Realtime servers, you need to add functionality to your game client so that players can join and participate in game sessions hosted with Amazon GameLift Servers Realtime.

There are two sets of tasks needed to prepare your game client: 
+ Set up your game client to acquire information about existing games, request matchmaking, start new game sessions, and reserve game session slots for a player.
+ Enable your game client to join a game session hosted on a Realtime server and exchange messages. 

## Find or create game sessions and player sessions
<a name="realtime-client-start-gamesession"></a>

Set up your game client to find or start game sessions, request FlexMatch matchmaking, and reserve space for players in a game by creating player sessions. 

**Important**  
As a best practice, we highly recommend that your create a backend service to make all direct requests to the Amazon GameLift Servers service. Set up game client actions that initiate the backent service to make requests and then relay relevant responses back to the game client. For more information about setting up a backend service, see [ Design your backend service for Amazon GameLift Servers](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift_quickstart_customservers_designbackend.html).

1. Add the AWS SDK to your game client, initialize an Amazon GameLift Servers client, and configure it to use the hosting resources in your fleets and queues. The AWS SDK is available in several languages; see the Amazon GameLift Servers SDKs [Amazon GameLift Servers development tools for game clients](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-supported.html#gamelift-supported-clients). 

1. Add Amazon GameLift Servers functionality to your backend service. For more detailed instructions, see [ Integrate your game client for Amazon GameLift Servers](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-client-api.html) and (optionally) [Adding FlexMatch matchmaking](https://docs.aws.amazon.com/gameliftservers/latest/flexmatchguide/match-intro.html). 

   Although not required, it is a best practice to use game session placement queues to create new game sessions. This method lets you take full advantage of Amazon GameLift Servers to choose the best possible locations to host new game sessions, based on a variety of factors, including player latency data. At a minimum, your backend service must use one of the available methods to request new game sessions and then handle game session data in response. You may also want to add optional functionality, such as to search for information on existing game sessions or to reserve player slots in a game session by creating individual player sessions.

1. Convey connection information back to the game client. The backend service receives game session and player session objects in response to requests to the Amazon GameLift Servers service. These objects contain information, in particular connection details (IP address and port) and player session ID, that the game client needs to connect to the game session running on a Realtime Server. 

## Connect to games on Amazon GameLift Servers Realtime
<a name="realtime-client-connect"></a>

Enable your game client to connect directly with a hosted game session on a Realtime server and exchange messages with the server and with other players.

1. Get the client SDK for Amazon GameLift Servers Realtime, build it, and add it to your game client project. See the README file for more information on SDK requirements and instructions on how to build the client libraries. 

1. Call [Client()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-client) with a client configuration that specifies the type of client/server connection to use.
**Note**  
If you're connecting to a Realtime server that is running on a secured fleet with a TLS certificate, you must specify a secured connection type.

1. Add the following functionality to your game client. See the [Amazon GameLift Servers Realtime client API (C\$1) reference](realtime-sdk-csharp-ref.md) for more information. 
   + Connect to and disconnect from a game 
     + [Connect()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-connect)
     + [Disconnect()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-disconnect)
   + Send messages to target recipients 
     + [SendMessage()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-sendmessage)
   + Receive and process messages 
     + [OnDataReceived()](realtime-sdk-csharp-ref-callbacks.md#realtime-sdk-csharp-ref-callbacks-ondata)
   + Join groups and leave player groups 
     + [JoinGroup()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-joingroup)
     + [RequestGroupMembership()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-requestgroupmembership)
     + [LeaveGroup()](realtime-sdk-csharp-ref-actions.md#realtime-sdk-csharp-ref-actions-leavegroup)

1. Set up event handlers for the client callbacks as needed. See [Amazon GameLift Servers Realtime client API (C\$1) reference: Asynchronous callbacks](realtime-sdk-csharp-ref-callbacks.md).

When working with Realtime fleets that have TLS certificate generation enabled, the server is automatically authenticated using the TLS certificate. TCP and UDP traffic is encrypted in flight to provide transport layer security. TCP traffic is encrypted using TLS 1.2, and UDP traffic is encrypted using DTLS 1.2.

## Game client examples
<a name="realtime-client-examples"></a>

### Basic realtime client (C\$1)
<a name="realtime-client-examples-basic"></a>

This example illustrates a basic game client integration with the client SDK (C\$1) for Amazon GameLift Servers Realtime. As shown, the example initializes a Realtime client object, sets up event handlers and implements the client-side callbacks, connects to a Realtime server, sends a message, and disconnects.

```
using System;
using System.Text;
using Aws.GameLift.Realtime;
using Aws.GameLift.Realtime.Event;
using Aws.GameLift.Realtime.Types;

namespace Example
{
    /**
     * An example client that wraps the client SDK for Amazon GameLift Servers Realtime
     * 
     * You can redirect logging from the SDK by setting up the LogHandler as such:
     * ClientLogger.LogHandler = (x) => Console.WriteLine(x);
     *
     */
    class RealTimeClient
    {
        public Aws.GameLift.Realtime.Client Client { get; private set; }
        
        // An opcode defined by client and your server script that represents a custom message type
        private const int MY_TEST_OP_CODE = 10;

        /// Initialize a client for Amazon GameLift Servers Realtime and connect to a player session.
        /// <param name="endpoint">The DNS name that is assigned to Realtime server</param>
        /// <param name="remoteTcpPort">A TCP port for the Realtime server</param>
        /// <param name="listeningUdpPort">A local port for listening to UDP traffic</param>
        /// <param name="connectionType">Type of connection to establish between client and the Realtime server</param>
        /// <param name="playerSessionId">The player session ID that is assigned to the game client for a game session </param>
        /// <param name="connectionPayload">Developer-defined data to be used during client connection, such as for player authentication</param>
       public RealTimeClient(string endpoint, int remoteTcpPort, int listeningUdpPort, ConnectionType connectionType,
                    string playerSessionId, byte[] connectionPayload)
        {
            // Create a client configuration to specify a secure or unsecure connection type
            // Best practice is to set up a secure connection using the connection type RT_OVER_WSS_DTLS_TLS12.
            ClientConfiguration clientConfiguration = new ClientConfiguration()
	     {
                // C# notation to set the field ConnectionType in the new instance of ClientConfiguration
	         ConnectionType = connectionType
	     };

            // Create a Realtime client with the client configuration            
            Client = new Client(clientConfiguration);

            // Initialize event handlers for the Realtime client
            Client.ConnectionOpen += OnOpenEvent;
            Client.ConnectionClose += OnCloseEvent;
            Client.GroupMembershipUpdated += OnGroupMembershipUpdate;
            Client.DataReceived += OnDataReceived;

            // Create a connection token to authenticate the client with the Realtime server
            // Player session IDs can be retrieved using AWS SDK for Amazon GameLift Servers
            ConnectionToken connectionToken = new ConnectionToken(playerSessionId, connectionPayload);

            // Initiate a connection with the Realtime server with the given connection information
            Client.Connect(endpoint, remoteTcpPort, listeningUdpPort, connectionToken);
        }

        public void Disconnect()
        {
            if (Client.Connected)
            {
                Client.Disconnect();
            }
        }

        public bool IsConnected()
        {
            return Client.Connected;
        }

        /// <summary>
        /// Example of sending to a custom message to the server.
        /// 
        /// Server could be replaced by known peer Id etc.
        /// </summary>
        /// <param name="intent">Choice of delivery intent i.e. Reliable, Fast etc. </param>
        /// <param name="payload">Custom payload to send with message</param>
        public void SendMessage(DeliveryIntent intent, string payload)
        {
            Client.SendMessage(Client.NewMessage(MY_TEST_OP_CODE)
                .WithDeliveryIntent(intent)
                .WithTargetPlayer(Constants.PLAYER_ID_SERVER)
                .WithPayload(StringToBytes(payload)));
        }

        /**
         * Handle connection open events
         */
        public void OnOpenEvent(object sender, EventArgs e)
        {
        }

        /**
         * Handle connection close events
         */
        public void OnCloseEvent(object sender, EventArgs e)
        {
        }

        /**
         * Handle Group membership update events 
         */
        public void OnGroupMembershipUpdate(object sender, GroupMembershipEventArgs e)
        {
        }

        /**
         *  Handle data received from the Realtime server 
         */
        public virtual void OnDataReceived(object sender, DataReceivedEventArgs e)
        {
            switch (e.OpCode)
            {
                // handle message based on OpCode
                default:
                    break;
            }
        }

        /**
         * Helper method to simplify task of sending/receiving payloads.
         */
        public static byte[] StringToBytes(string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }

        /**
         * Helper method to simplify task of sending/receiving payloads.
         */
        public static string BytesToString(byte[] bytes)
        {
            return Encoding.UTF8.GetString(bytes);
        }
    }
}
```

# Upload a script for Amazon GameLift Servers Realtime servers
<a name="realtime-script-uploading"></a>

When you're ready to deploy Amazon GameLift Servers Realtime for your game, upload completed Realtime server script files to Amazon GameLift Servers. Do this by creating an Amazon GameLift Servers script resource and specifying the location of your script files. You can also update server script files that are already deployed by uploading new files for an existing script resource.

When creating a script, you can choose the Node.js runtime version. Node.js 24 runs on Amazon Linux 2023, while Node.js 10 uses Amazon Linux 2. Amazon GameLift Servers automatically manages Node.js minor and patch version updates for new fleets. The runtime will remain unchanged for a fleet once it is created. If you would like to pick a specific minor and patch version of Node.js you can install it using an install script. See [Add an install script (optional)](#realtime-script-uploading-install-script).

When you create a new script resource, Amazon GameLift Servers assigns it a unique script ID (for example, `script-1111aaaa-22bb-33cc-44dd-5555eeee66ff`) and uploads a copy of the script files. Upload time depends on the size of your script files and on your connection speed.

After you create the script resource, Amazon GameLift Servers deploys the script with a new Amazon GameLift Servers Realtime fleet. Amazon GameLift Servers installs your server script onto each instance in the fleet, placing the script files in `/local/game`.

To troubleshoot fleet activation problems related to the server script, see [Debug managed EC2 fleets for Amazon GameLift Servers Realtime](fleets-creating-debug-realtime.md).

## Package script files
<a name="realtime-script-uploading-packaging"></a>

Your server script can include one or more files combined into a single .zip file for uploading. The .zip file must contain all files that your script needs to run.

You can store your zipped script files in either a local file directory or in an Amazon Simple Storage Service (Amazon S3) bucket.

### Add an install script (optional)
<a name="realtime-script-uploading-install-script"></a>

Similar to [ Add a build install script](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-build-cli-uploading-install.html) for an Amazon GameLift Servers build, you can optionally add an install script to customize the runtime environment for your Realtime script. This feature is only available for scripts using Node.js version 24 and later.

To add an install script, include a file named `install.sh` in the root directory of your script .zip file. Amazon GameLift Servers will automatically detect and execute this script during fleet deployment.

**Note**  
The install script only executes during fleet creation. If you update an existing script using [UpdateScript](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_UpdateScript.html), the install script will not be executed on fleets that are already running. To apply install script changes, you must create a new fleet with the updated script.

**Example Install script example**  
This example `install.sh` file installs Node.js 24.10.0 to replace the default Node.js 24 runtime:  

```
#!/bin/bash

# Remove existing Node.js installation
sudo rm -rf /local/NodeJS/*

# Install Node.js v24.10.0
curl -L https://nodejs.org/dist/v24.10.0/node-v24.10.0-linux-x64.tar.xz | sudo tar -xJ -C /local/NodeJS --strip-components=1
```

# Upload script files from a local directory
<a name="realtime-script-uploading-zip"></a>

If you have your script files stored locally, you can upload them to Amazon GameLift Servers from there. To create the script resource, use either the Amazon GameLift Servers console or the [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/).

------
#### [  Amazon GameLift Servers console ]

**To create a script resource**

1. Open the [Amazon GameLift Servers console](https://console.aws.amazon.com/gamelift/).

1. In the navigation pane, choose **Hosting**, **Scripts**.

1. On the **Scripts** page, choose **Create script**.

1. On the **Create script** page, under **Script settings,** do the following:

   1. For **Name**, enter a script name.

   1. (Optional) For **Version**, enter version information. Because you can update the content of a script, version data can be helpful in tracking updates.

   1. For **Node.js version**, choose the runtime version of Node.js the server will run on.

   1. For **Script source**, choose **Upload a .zip file**.

   1. For **Script files**, choose **Choose file**, browse for the .zip file that contains your script, and then choose that file.

1. (Optional) Under **Tags**, add tags to the script by entering **Key** and **Value** pairs.

1. Choose **Create**.

   Amazon GameLift Servers assigns an ID to the new script and uploads the designated .zip file. You can view the new script, including its status, on the **Scripts** page.

------
#### [ AWS CLI ]

Use the [https://docs.aws.amazon.com/cli/latest/reference/gamelift/create-script.html](https://docs.aws.amazon.com/cli/latest/reference/gamelift/create-script.html) AWS CLI command to define the new script and upload your server script files.

**To create a script resource**

1. Place the .zip file into a directory where you can use the AWS CLI.

1. Open a command line window and switch to the directory where you placed the .zip file.

1. Enter the following **create-script** command and parameters. For the **--zip-file** parameter, be sure to add the string `fileb://` to the name of the .zip file. It identifies the file as binary so that Amazon GameLift Servers processes the compressed content.

   ```
   aws gamelift create-script \
       --name user-defined name of script \
       --script-version user-defined version info \
       --zip-file fileb://name of zip file \
       --node-js-version 10.x or 24.x \
       --region region name
   ```

   *Example*

   ```
   aws gamelift create-script \
       --name "My_Realtime_Server_Script_1" \
       --script-version "1.0.0" \
       --zip-file fileb://myrealtime_script_1.0.0.zip \
       --node-js-version 24.x \
       --region us-west-2
   ```

   In response to your request, Amazon GameLift Servers returns the new script object.

1. To view the new script, call `[describe-script](https://docs.aws.amazon.com/cli/latest/reference/gamelift/describe-script.html)`.

------

# Upload script files from Amazon S3
<a name="realtime-script-uploading-s3"></a>

You can store your script files in an Amazon S3 bucket and upload them to Amazon GameLift Servers from there. When you create your script, you specify the S3 bucket location and Amazon GameLift Servers retrieves your script files from Amazon S3.

**To create a script resource**

1. **Store your script files in an S3 bucket.** Create a .zip file containing your server script files and upload it to an S3 bucket in an AWS account that you control. Take note of the object URI—you need this when creating an Amazon GameLift Servers script.
**Note**  
Amazon GameLift Servers doesn't support uploading from S3 buckets with names that contain a period (.).

1. **Give Amazon GameLift Servers access to your script files.** To create an AWS Identity and Access Management (IAM) role that allows Amazon GameLift Servers to access the S3 bucket containing your server script, follow the instructions in [ Set up an IAM service role for Amazon GameLift Servers](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/setting-up-role.html). After you create the new role, take note of its name, which you need when creating a script.

1. **Create a script.** Use the Amazon GameLift Servers console or the AWS CLI to create a new script record. To make this request, you must have the IAM `PassRole` permission, as described in [ IAM permission examples for Amazon GameLift Servers](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-iam-policy-examples.html).

------
#### [ Console ]

1. In the [Amazon GameLift Servers console](https://console.aws.amazon.com/gamelift), in the navigation pane, choose **Hosting**, **Scripts**.

1. On the **Scripts** page, choose **Create script**.

1. On the **Create script** page, under **Script settings**, do the following:

   1. For **Name**, enter a script name.

   1. (Optional) For **Version**, enter version information. Because you can update the content of a script, version data can be helpful in tracking updates.

   1. For **Node.js version**, choose the runtime version of Node.js the server will run on.

   1. For **Script source**, choose **Amazon S3 URI**.

   1. Enter the **S3 URI** of the script object that you uploaded to Amazon S3, and then choose the **Object version**. If you don't remember the Amazon S3 URI and object version, choose **Browse S3**, and then search for the script object.

1. (Optional) Under **Tags**, add tags to the script by entering **Key** and **Value** pairs.

1. Choose **Create**.

   Amazon GameLift Servers assigns an ID to the new script and uploads the designated .zip file. You can view the new script, including its status, on the **Scripts** page.

------
#### [ AWS CLI ]

Use the [https://docs.aws.amazon.com/cli/latest/reference/gamelift/create-script.html](https://docs.aws.amazon.com/cli/latest/reference/gamelift/create-script.html) AWS CLI command to define the new script and upload your server script files.

1. Open a command line window and switch to a directory where you can use the AWS CLI.

1. Enter the following **create-script** command and parameters. The **--storage-location** parameter specifies the Amazon S3 bucket location of your script files.

   ```
   aws gamelift create-script \
       --name [user-defined name of script] \
       --script-version [user-defined version info] \
       --storage-location "Bucket"=S3 bucket name,"Key"=name of zip file in S3 bucket,"RoleArn"=Access role ARN \
       --node-js-version 10.x or 24.x \
       --region region name
   ```

   *Example*

   ```
   aws gamelift create-script \
       --name "My_Realtime_Server_Script_1" \
       --script-version "1.0.0" \
       --storage-location "Bucket"="gamelift-script","Key"="myrealtime_script_1.0.0.zip","RoleArn"="arn:aws:iam::123456789012:role/S3Access" \
       --node-js-version 24.x \
       --region us-west-2
   ```

   In response to your request, Amazon GameLift Servers returns the new script object.

1. To view the new script, call [https://docs.aws.amazon.com/cli/latest/reference/gamelift/describe-script.html](https://docs.aws.amazon.com/cli/latest/reference/gamelift/describe-script.html).

------

# Update an Amazon GameLift Servers Realtime script
<a name="realtime-script-uploading-update"></a>

You can update the metadata for a script resource using either the Amazon GameLift Servers console or the [https://docs.aws.amazon.com/cli/latest/reference/gamelift/update-script.html](https://docs.aws.amazon.com/cli/latest/reference/gamelift/update-script.html) AWS CLI command.

You can also update the script content for a script resource. Amazon GameLift Servers deploys script content to all fleet instances that use the updated script resource. When the updated script is deployed, instances use it when starting new game sessions. Game sessions that are already running at the time of the update don't use the updated script.

**To update script files**
+ For script files stored locally, to upload the updated script .zip file, use either the Amazon GameLift Servers console or the **update-script** command.
+ For script files stored in an Amazon S3 bucket, upload the updated script files to the S3 bucket. Amazon GameLift Servers periodically checks for updated script files and retrieves them directly from the S3 bucket.