Skip to main content

Finding the Best Region for a Player

GameFlow exposes lightweight ping endpoints for each region so game clients can measure latency and select the best region for a match. Both HTTP and UDP are supported.

Ping Endpoints​

Each region exposes a ping endpoint over two protocols:

  • HTTP, GET returns 200 OK with minimal payload. Simple, works everywhere, subject to TLS/TCP handshake overhead.
  • UDP, echo server on port 8080. Sends back packet payload verbatim. Closer to real gameplay traffic, no handshake, lower overhead.
RegionHTTPUDP
US Easthttps://us-east.ping.gameflow.ggus-east.ping.gameflow.gg:8080
US Westhttps://us-west.ping.gameflow.ggus-west.ping.gameflow.gg:8080
EU Centralhttps://eu-central.ping.gameflow.ggeu-central.ping.gameflow.gg:8080
AP Southeasthttps://ap-southeast.ping.gameflow.ggap-southeast.ping.gameflow.gg:8080

Prefer UDP for matchmaking decisions, measured RTT matches what the game server connection will experience. Use HTTP when UDP is blocked (restrictive networks, browsers).

Measuring Latency​

Send a request to each endpoint and measure round-trip time. For UDP, send a small payload and wait for the echo. Compare results to pick the lowest-latency region.

HTTP​

using System.Collections;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.Networking;

public class RegionPing : MonoBehaviour
{
private static readonly string[] Regions = {
"us-east", "us-west", "eu-central", "ap-southeast"
};

public void PingAllRegions()
{
foreach (var region in Regions)
{
StartCoroutine(PingRegion(region));
}
}

private IEnumerator PingRegion(string region)
{
var url = $"https://{region}.ping.gameflow.gg";
var sw = Stopwatch.StartNew();

using var request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();

sw.Stop();

if (request.result == UnityWebRequest.Result.Success)
{
UnityEngine.Debug.Log($"Ping to {region}: {sw.ElapsedMilliseconds} ms");
}
}
}

UDP​

Send a small packet to port 8080 and time the echo. No handshake, so RTT reflects raw network latency.

using System.Diagnostics;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public static class UdpPing
{
public static int? Ping(string region, int timeoutMs = 2000)
{
using var udp = new UdpClient();
udp.Client.ReceiveTimeout = timeoutMs;
udp.Connect($"{region}.ping.gameflow.gg", 8080);

var payload = Encoding.ASCII.GetBytes("ping");
var sw = Stopwatch.StartNew();
udp.Send(payload, payload.Length);

try
{
System.Net.IPEndPoint ep = null;
udp.Receive(ref ep);
sw.Stop();
return (int)sw.ElapsedMilliseconds;
}
catch (SocketException) { return null; }
}
}

Using the Best Region​

Once you've determined the best region, pass it when requesting a game server via the GameFlow API. There are two approaches depending on your setup.

Standalone Server​

Start a one-off game server with POST /v1/games/:gameId/servers. GameFlow provisions the server and blocks until it's ready, returning its IP and port.

const bestRegion = (await pingAllRegions())[0].region;

const response = await fetch(
`https://api.gameflow.gg/v1/games/${gameId}/servers`,
{
method: "POST",
headers: { "X-Api-Key": apiKey },
body: JSON.stringify({
region: bestRegion,
buildId: "build_abc123",
payload: JSON.stringify({ players, teamA, teamB }),
}),
}
);

const { server } = await response.json();
// server.address, server.port

Fleet Allocation (Autoscaling)​

If you have autoscaling configured via a fleet, allocate a pre-warmed server with POST /v1/fleets/:gameId/allocate. This returns an already-running server from the pool, so it's faster than starting a standalone server.

const bestRegion = (await pingAllRegions())[0].region;

const response = await fetch(
`https://api.gameflow.gg/v1/fleets/${gameId}/allocate`,
{
method: "POST",
headers: { "X-Api-Key": apiKey },
body: JSON.stringify({
region: bestRegion,
payload: JSON.stringify({ players, teamA, teamB }),
}),
}
);

const { allocation } = await response.json();
// allocation.address, allocation.port

See the Custom Game Backend guide for a full integration walkthrough.

Best Practices​

  • Prefer UDP when available, matches real gameplay traffic and avoids TLS/TCP handshake overhead. Fall back to HTTP when UDP is blocked (browsers, restrictive corporate networks).
  • Ping on game launch or lobby entry, avoid pinging mid-match to reduce unnecessary network traffic.
  • Let the player override, display the results and allow the player to manually select a region if they prefer.
  • Discard the first ping, HTTP includes TLS handshake overhead; UDP may warm up DNS/routing caches. Drop the first sample and average the rest.
  • Ping multiple times and average, a single request can be affected by cold connections or transient network conditions. Averaging 3-5 pings per region gives a more stable result.
  • Set a timeout on UDP, UDP does not guarantee delivery. Treat no-response within ~2s as a failed sample and retry or mark region unreachable.