PlayFlow also has a native lobby and matchmaking system. If you’re starting fresh, that path is simpler — no PlayFab required. Use this bridge when you specifically want to keep PlayFab’s matchmaker or player identity.
- You currently use PlayFab (a title, a matchmaking queue, and some registered players).
- You have a PlayFlow project and a dedicated Linux server build ready to upload. See the Docker builds guide or the Unity quickstart if you don’t yet.
How it works
A CloudScript rule calls PlayFlow
A PlayFab Automation rule runs a CloudScript function that calls
POST /api/v3/servers/start, passing the PlayFab match ID, title secret, and player list as environment variables.PlayFlow launches the server
PlayFlow allocates the network ports immediately and boots your build. It injects everything the server needs as environment variables (
PLAYFLOW_PORTS, your custom vars, and API credentials).The server publishes its address
On startup, the server reads its own public
host:port from PLAYFLOW_PORTS and writes it into each matched player’s PlayFab Player Data — keyed by the match ID.Step 1 — Prepare your PlayFlow project
Get a server API key
In your PlayFlow dashboard, open your project’s API Keys and copy a server key (
pf_...). This key can start servers and must stay secret — treat it exactly like your PlayFab Title Secret. Never ship it in a client build.Upload your server build
Upload your dedicated Linux server build and give it a name (for example
space-edge). PlayFlow references builds by this name — the value becomes the version_tag you pass when starting a server, and each upload under the same name auto-increments its version. See Docker builds for the upload flow.Configure a network port
In your project settings, add a port config and give it a name you’ll look up later — this guide uses
game. Choose UDP for most game netcode (for example FishNet’s Tugboat transport), or TCP (optionally with TLS) for WebSocket-based clients. PlayFlow allocates the public port at launch; your server reads it back from PLAYFLOW_PORTS.Step 2 — Create the PlayFab CloudScript function
Log in to PlayFab, open your title, and under Automation → Revisions (Legacy) deploy a new revision containing the function below. It calls PlayFlow’s start endpoint and forwards everything the server will need. Update the four variables at the top with your own values first. ThePlayFlow_BuildName must match the build name you uploaded in Step 1.
PlayFlow returns the
instance_id, a status of launching, and the allocated network_ports synchronously from this call — the ports are reserved before the machine boots. This guide has the server publish the address (Step 4) so that connection info appears in Player Data exactly when the server is ready. If you’d rather publish from CloudScript, you can instead poll GET /api/v3/servers/{instance_id} until status is running and read network_ports from the response.Step 3 — Add the automation rule
Under Automation → Rules, create a new rule:- Event Type:
playfab.matchmaking.match_found - Action → Type:
Execute Entity CloudScript - CloudScript Function:
StartPlayFlowDeployment
Step 4 — Publish the address from the server
When PlayFlow starts your server, it injects these environment variables into the container (alongside anyenvironment_variables you passed from CloudScript):
| Variable | Description |
|---|---|
PLAYFLOW_PORTS | JSON array of the server’s public ports: [{ "name", "internal_port", "external_port", "protocol", "host", "tls_enabled" }] |
PLAYFLOW_INSTANCE_ID | This server’s instance ID |
PLAYFLOW_API_KEY / PLAYFLOW_API_URL | Credentials + base URL to call the PlayFlow API back if needed |
PLAYFLOW_REGION | The region the server launched in |
| Your custom vars | PLAYFAB_MATCH_ID, PLAYFAB_TITLE_SECRET, PLAYFAB_MATCH_PLAYERS_ID_LIST |
PLAYFLOW_PORTS, then write host:external_port into each matched player’s Player Data, keyed by the match ID.
PlayerDataUpdateService.cs
Server/UpdateUserData:
PlayfabRestApiService.cs (server)
Step 5 — Connect from the client
The client side is pure PlayFab and identical to any PlayFab matchmaking integration — PlayFlow isn’t involved until the client reads the address. The flow:Log in
Authenticate the player with PlayFab (for example
LoginWithCustomID) and store the entity + session tokens.Wait for a match
Poll
Match/GetMatchmakingTicket every few seconds until Status is Matched, then store the MatchId.Reading the address and connecting (client)
Step 6 — Build, upload, and test
Build a headless Linux server
Produce a dedicated Linux server build with your netcode configured to start on headless and listen on the internal port that matches your PlayFlow port config.
Upload it to PlayFlow
Upload the build under the same name you referenced as
PlayFlow_BuildName in the CloudScript (space-edge here). See Docker builds.Why this works well on PlayFlow
- The server is handed its own public address.
PLAYFLOW_PORTScontains the resolvedhostandexternal_portfor every named port — no self-lookup or metadata call required. - Readiness is automatic. Because the server writes Player Data in
OnStartServer, connection info only appears once the process is actually up. Clients that poll can’t grab a dead address. - The server can talk back to PlayFlow.
PLAYFLOW_API_KEYandPLAYFLOW_API_URLare injected too, so the server can stop itself when the match ends (DELETE /api/v3/servers/{instance_id}) or update its own metadata — no extra secrets to manage. - Set a TTL as a safety net. Pass a
ttl(seconds) onPOST /servers/startso an abandoned match can’t leave a server running forever. See the API reference.
When you’re ready to simplify further, PlayFlow’s native matchmaking removes the PlayFab round-trip entirely — the matchmaker launches the server and hands the connection details straight to your players over a real-time channel.