Production checklist
This page gathers the items you will tick off one by one before going live. Each item comes with a short reason and links to the relevant page. Review the list once before launch and again after every major change.
1. Network and hosting
- Everything is HTTPS. Session cookies have the
__Secure-prefix and carry theSecureflag; a session cannot be established over plain HTTP. Sockets are opened withwss://. If you usehttp://localhostin local development, verify your browser’slocalhostexception. - Browser call path chosen. Either the game’s domain is in an environment’s domain list and the game calls Open Play directly (the server sends CORS headers; the game and Open Play must be subdomains of the same registrable domain, otherwise the
SameSite=Laxsession cookie is not sent), or the game calls the API from under its own domain through a reverse proxy (architecture and hosting). - The proxy forwards these headers as they are:
Authorization,Cookie(andSet-Cookiein the response),Origin,x-crx-env,x-csrf-token,Idempotency-Key,If-Match,x-crx-schema-version,Sec-WebSocket-*(including subprotocol and extension negotiation). It does not strip the response headers (x-csrf-token,Deprecation,Retry-After,ETag). - The WebSocket upgrade is open on the proxy, the
Upgrade/Connectionheaders are forwarded, and the connection can stay idle for at least 5 minutes (the server does the idle close itself: limits). - The request body limit is at least 2 MiB. The server rejects anything above 2 MiB with
413; your proxy should not set a lower limit. - Timeout: the proxy’s response-header wait time does not cut off long operations (Open Play’s own gateway uses 65 s).
- The client IP is forwarded. The rate limits on the identity endpoints depend on the client IP. If the proxy does not add
X-Forwarded-For, all players gather in a single bucket (for example guest opening is 30 per minute). If multiple proxies are chained, the operator must define the trusted proxy blocks. - The panel path is closed to the internet. The
/v1/panel/*path returns404on the public gateway; the panel is reached only from the management network or from a separate domain. - Caching: API responses that carry a cookie or
Authorizationare not put in a shared cache (CDN). Only public, content-addressed responses (/v1/assets/{sha256},/v1/model-files/{sha256}) and catalog responses that carry anETagare subject to an appropriate caching rule.
2. Environments and domains
- You use separate environments for development, staging, and live; data is not shared.
- Each environment’s domain is defined in the panel (Game settings: environments); this is the allowed
Originlist. - The correct environment ID (the
x-crx-envvalue) is in the client configuration; the live client does not point to the staging environment. - Only the needed modules are on (modules). A disabled module returns
404 module_disabled; every module you leave on is an attack surface. - Sign-in methods are configured in the panel (guest, email, Google); the methods you do not use are off (Sign-in methods).
3. Keys and secrets
- Server keys are only on the server. They are not in the client bundle, the mobile app, the WebGL build, or the repository (security).
- A separate key per environment and service; the keys have been given an expiry date.
- If you use a client key, you have verified that you know which endpoints it can call; player operations are done with the player session (endpoints).
- A key rotation rehearsal was done: second key, rollout, revoke the old one.
- Keys and tokens are not in the logs;
Authorization,Cookie, andx-csrf-tokenare filtered. - The webhook secret is in your receiver’s secret manager; because it is shown only once at registration, it has a backup.
4. Replay safety and concurrency
- Every call that grants money, items, rewards, or sends a command carries an
Idempotency-Key; the key is generated once and used exactly on repeats (idempotency). - On an uncertain outcome (timeout, network drop), the command is completed with the same key, not a new one, or with the result query.
- Calls that write a shared resource send
If-Match/expectedVersion; on409the state is re-read. - There is exponential backoff + jitter on
429,503, and network errors;Retry-Afteris respected (rate limits). - Error handling is by status code; the plain-text message is not parsed (errors).
5. Player identity
- The session-loss flow is set up: session refresh when
401arrives, otherwise sign in again; a separate screen for a banned account (sessions and CSRF). - The guest identity’s storage behavior and the upgrade flow to email or Google are set up (guest progress is kept with the upgrade).
- Your game server verifies the access JWT with the JWKS, checking the expiry and environment fields (server verification).
- The identity rate limits (guest 30/min, email sign-in 5/min, sign-up 10/min, per IP) can carry your expected launch traffic; a load test was done if needed.
6. Realtime
- The client uses the SDK or implements the protocol (ticket,
Origin, subprotocol) completely (protocol). - Reconnect: a new ticket on every connection, exponential backoff,
Joinwith the last cursor on durable streams,Joinwithout a cursor onResyncRequired(reconnect). - There is a “Continue” screen for idle close (
4100); a keep-alive input is sent on pause screens. - The frame rate is below 40/s; the limit of 4 tabs/sockets per player is known.
- The notification and chat sockets cannot be opened directly from the browser (header restriction); inbox polling or the REST endpoints are used (realtime overview).
7. Plugins
- The schema digest (
schemaSha256) of the plugin you use is written into your release manifest and the bindings were generated with this digest (bindings). - A digest comparison (at startup or in CI) is done after a server update.
- The plugin’s state in the environment is enabled (Plugins); this is the first place to look for an unexpected
403 forbidden. - A migration task was opened for calls that carry the
Deprecationheader (versioning).
8. Webhooks
- The endpoint is
https; the signature is verified on every request, the timestamp window is checked, and deduplication is done withX-Crx-Event-Id(security). - The receiver returns a fast
2xx(queues the work); there is a monitoring plan for deliveries that end upfailed(DLQ) after 10 attempts (Webhooks and event queue offers only monitoring, there is no resend); you have a way to make up for missed events by reading the relevant resource with REST.
9. Observability and operations
- Your request log has the status code, duration, called path, and (on plugin endpoints)
x-request-id; there are no secret values. - You have an alert for the
5xxand429rate; it was verified that503+Retry-Afterresponses are retried. - Panel admin accounts are personal and two-factor authentication is on (Panel operators).
- The operation history is reviewed regularly; the safety switches are in their default position (if you changed them deliberately, the reason is recorded).
- The SDK version is pinned exactly (no
^); upgrades are followed from the changelog (versioning).
10. Final rehearsal before launch
- Run the end-to-end flow in a staging environment similar to the live one: sign-in, reward, purchase, socket connection, connection drop, and reconnect.
- Deliberately send the same request twice with the same
Idempotency-Key; verify that the second response returns the same result. - Revoke a server key once and observe the switch to the second key.
- Send a request with a wrong signature to your webhook receiver; verify that it rejects it.
- Do a trial on the identity endpoints that imitates your launch traffic; look at the
429rate.
If problems come up, see the troubleshooting page.