Photon Engine: Designing a Room‑Based Relay with Optional Server Authority
Guidance on when Photon Realtime/PUN’s client‑relay model is sufficient, how to add minimal authority via Master Client and CAS properties, and when to move to plugins or webhooks for validation and persistence.
05 Apr 2026, 03:43 UTC

Requirements
Before choosing a Photon architecture, list the functional and non‑functional needs of your game:
- Real‑time interaction latency tolerance (e.g., < 100 ms for action games, higher for turn‑based).
- Number of concurrent players per room and expected message rate.
- Whether game outcomes must be tamper‑proof (competitive scoring, economy, anti‑cheat).
- Persistence needs: does room state survive a server restart or region failover?
- Operational constraints: budget (CCU/message‑rate) vs. willingness to run self‑hosted Photon Server.
If the answers point to casual/co‑op play, low message rates, and no strict outcome integrity, the pure client‑relay model may be enough. Otherwise, you need to plan for authority.
Smallest Suitable Design
The minimal viable setup uses Photon Realtime (or PUN) in its default room‑based relay mode:
- Clients join a room; the server merely forwards events and room/player property updates.
- One client is elected as the
MasterClient. Photon automatically transfers this role when the current master disconnects. - Shared decisions (object spawns, turn order, simple scoring) are made by the master client and broadcast via
RaiseEvent. - Contended writes (e.g., two players trying to claim the same spawn slot) are handled with Room Properties using the Check‑and‑Swap (CAS) expected‑value mechanism.
This design requires no custom server code and works within the free tier limits of Photon Cloud, provided the room stays under the product’s message‑rate ceiling.
Example: Claiming a Slot with CAS
// C# (PUN 2)
bool TryClaimSlot(int slotId, int claimedByPlayerId)
{
string key = "slot_" + slotId;
int expected = -1; // -1 means free
bool success = PhotonNetwork.CurrentRoom.SetPropertiesIfNotExists(
new ExitGames.Client.Photon.Hashtable { { key, claimedByPlayerId } },
new ExitGames.Client.Photon.Hashtable { { key, expected } }
);
return success; // true only if the slot was free and now owned by this player
}
The server guarantees that exactly one client will see true for a given slot, even if two clients call the method simultaneously.
Trust and Data Boundaries
In the pure relay model the server does not validate event payloads. The trust boundary is therefore:
- Client → Server: any
RaiseEventcontent is accepted and forwarded. - Server → Client: only room/player property updates and event relays are trusted; the server does not reinterpret them.
Consequences:
- Anti‑cheat, secure economy, and competitive fairness must be enforced elsewhere (client‑side heuristics, Master Client logic, or server‑side plugins).
- Room Properties are the only server‑enforced primitive; they are per‑key CAS operations, not general transactions.
Operational Checks
To verify that the chosen design stays within limits and behaves as expected, run these checks in a staging environment:
- Master Client migration test: start a room with two clients, designate one as master, perform a master‑only action (e.g., spawn), then kill the master client process. Observe whether the action is duplicated, lost, or correctly retaken by the new master.
- CAS contention test: have N clients repeatedly attempt to claim the same slot using the CAS method above. Count successes; exactly one should succeed per attempt.
- Message‑rate monitoring: enable Photon’s built‑in diagnostics (
PhotonNetwork.NetworkClientStateandLoadBalancingClient.LoadStatistics) and record messages/second per room. Compare against your plan’s published limit (e.g., 500 msg/s/rooms for the free tier). - Webhook outage simulation (if using persistence): point the webhook URL to a non‑responsive endpoint, create a room, add some property updates, then disconnect all players. Verify that the room closes and that the expected webhook callbacks (
PathClose,PathGameClose) are attempted (check logs).
All checks should be performed with client builds that match the production version; do not rely on editor‑only shortcuts.
Failure Modes
Even with the smallest design, be aware of these failure modes:
- Master Client disconnect mid‑decision: if the master crashes after deciding but before broadcasting the result, other clients may never see the outcome, leading to stale state. Mitigation: persist critical decisions in Room Properties (CAS) before broadcasting, or have clients re‑query the master after a timeout.
- Region failover without persistence: Photon Cloud does not automatically migrate rooms between regions. A regional outage will destroy the room unless you have enabled webhooks that persist room state to your backend.
- Message‑rate throttling: when a room exceeds its allowed messages/second, the server silently drops excess events. Gameplay may degrade (missed inputs, delayed updates) before any disconnect is visible. Monitor
LoadStatistics.PeerCountandLoadStatistics.MessageRateto detect throttling early. - CAS limited to single keys: complex invariants (e.g., "slot A and slot B cannot both be occupied by the same player") cannot be enforced with properties alone; you need a plugin or authoritative server to evaluate multi‑key logic.
When to Change the Design
Re‑evaluate the architecture if any of the following conditions become true:
- Competitive integrity is required (ranked matches, betting, item trading). Move to Photon Server plugins or a custom authoritative backend that validates every
RaiseEventbefore forwarding. - Room state must survive server restarts or region failures. Enable IsPersistent webhooks (
PathCreate,PathClose,PathGameClose) and ensure your HTTP endpoint writes room snapshots to a durable store. - Expected message rate approaches or exceeds the plan’s limit despite interest groups and event caching. Consider sharding the game across multiple rooms, reducing event frequency, or upgrading to a higher‑tier plan.
- You need multi‑key transactions or complex game logic (e.g., turn‑based board with rule validation). Deploy a Photon Server plugin that intercepts events, applies authority, and optionally forwards only approved events.
- Operational overhead of self‑hosting Photon Server becomes acceptable compared to CCU/message‑rate costs, and you want full control over logging, scaling, and custom auth.
When moving to plugins, remember that the plugin runs in the server’s message path, so any unhandled exception will disconnect the room. Implement thorough unit tests and use Photon’s plugin SDK logging to capture failures before they affect players.
Summary
Start with the client‑relay model, use the Master Client for simple arbitration, and rely on Room Properties CAS for the only server‑guaranteed consistency. Add persistence or authority only when the requirements for trust, durability, or scalability demand it, and validate the change with the operational checks outlined above.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.