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
1
PlayFab matches players
PlayFab’s matchmaker fires a
playfab.matchmaking.match_found event.2
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.3
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).4
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.5
Clients connect
Each client polls its PlayFab ticket until matched, then reads the connection info from Player Data and connects. Because the server only writes Player Data once it’s actually running, clients never get a stale address.
Step 1 — Prepare your PlayFlow project
1
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.2
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.3
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):
On startup, read the public address for your named port out of
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:1
Log in
Authenticate the player with PlayFab (for example
LoginWithCustomID) and store the entity + session tokens.2
Create a ticket
Call
Match/CreateMatchmakingTicket on your queue and keep the returned ticket ID.3
Wait for a match
Poll
Match/GetMatchmakingTicket every few seconds until Status is Matched, then store the MatchId.4
Read the address & connect
Poll
Client/GetUserData with the MatchId as the key until the server has written it, then set your transport’s address/port and connect. Retry for a few seconds — the server writes Player Data the moment it boots, which is typically a few seconds after the match.Reading the address and connecting (client)
Step 6 — Build, upload, and test
1
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.
2
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.3
Run two clients
Launch two PlayFab-authenticated clients and start matchmaking on both. When PlayFab matches them, your rule fires, PlayFlow boots the server, the server publishes its address, and both clients connect to the same deployment.
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.