Skip to content

Production Readiness

RevTurbine is safe to run in production from day one: we add no latency and our availability never affects your product. Decisions never have critical dependence on our servers. The RevTurbine SDK runs inside your app, and on your backend where you verify. It evaluates entitlements and placements locally, as a pure function of your Playbook and the current user context.

We push additional inputs to your local engine: aggregated frequency caps, prioritization scores as available. These are additive; nothing breaks or blocks if not present. This page is the checklist for the rest.

The one decision that matters most: the client check drives the UI; your server makes the money-safe decision. Read Client vs Server Enforcement before shipping anything billing-critical.

RevTurbine issues three kinds of key. Two you create in the dashboard; the third your backend mints at runtime. There is no live/test split on keys; use environmentId (below) and test: true to separate traffic.

KeyLooks likeLives inWhat it does
Ingest keyrtk_… (type public)Your browser bundle — safe to shipThe browser’s key: Playbook delivery, event ingest, client-safe reads. Bound to an origin allowlist; cannot call management APIs. Create it at Settings → API tokens → Ingest keys.
Server keyrtk_… (type server)Your backend onlyProgrammatic calls to the RevTurbine API from your server — Playbook delivery, management APIs — and minting the session keys below. Refused on a browser-like request. Create it at Settings → API tokens → Server token.
Session keyrt_client_…The browser, in memory, short-lived (~10 minutes)Lets the browser poll one user’s server-derived context — plan, trial, payment state — straight from RevTurbine (GET /api/sdk/client-context). Your backend mints it per user with the server key (POST /api/sdk/client-sessions); the SDK asks for it through your clientSession callback and re-mints on expiry.

Which one goes where:

  • In the browser, pass the ingest key as publicKey. The name says what it is: a scanner or an agent that finds publicKey in a bundle knows it belongs there. As of 0.11.0 it is the only name accepted there — ingestPublicKey was removed and apiKey is no longer read as a browser credential (BL-0113), so a browser init without publicKey fails instead of sending the wrong key. Never a server key: RevTurbine refuses one presented from a browser.
  • On your backend, pass the server key as apiKey — on the server SDK and on the headless SDK alike; the sample on Server-Side Integration reads it from REVTURBINE_API_KEY — and use it to mint session keys.
  • For server-derived context in the browser, hand the SDK a clientSession callback that returns a session key from your backend. See Configuration → Server-derived context.
  • Local mode needs no key at all.

Two further credentials exist for tooling, not for SDK wiring: the CLI’s own rtk_… (type client) from revturbine login, one per machine; and an rtk_… (type mcp) for agent tooling, from Settings → API tokens → MCP.

Stamp environmentId ('production' / 'staging') so analytics stays separated by deployment, and test: true on instances that generate test traffic.

Pin @revturbine/sdk and the CLI per project; revturbine --help from the project-pinned CLI is authoritative for its command surface. A change to any @public signature requires a CHANGELOG entry — CI enforces it — and the Playbook schema version the SDK expects is listed on the Compatibility Matrix. Pin the SDK to a version whose schema matches the Playbook you deploy.

A check that can’t justify a grant denies rather than leaking a paid feature — the reason codes say why. The Playbook is cached locally, so real answers need no round trip, and billing-critical actions are re-checked on your server before value is granted. Tune what a slot renders on provider failure with providerFailureSlotBehavior (default: render nothing). See Error Handling.

In local_only mode the SDK evaluates entirely from the bundled Playbook — no network. That’s great for tests and no-backend demos, but be aware:

  • Usage is client-reported and client-only — not authoritative. Don’t meter billing off it.
  • There are no real-time config updates — you ship a Playbook snapshot.
  • Events go to localStorage, not the ingest pipeline.

See Runtime Modes to choose between local mode (local_only), hosted mode (revturbine_server), and custom_endpoints.

The SDK caches placement decisions and interaction state per user and persists them, so repeat checks are instant and dismiss/snooze survive reloads. The cache clears on identity change (identify / reset) and when the config updates. If you see a stale decision after a config change, confirm the user context was re-identified.

Every placement decision carries the config_version it was evaluated against, so you can trace a decision back to the exact Playbook that produced it. A Playbook moves from draft → Release, so each launched change is reviewed, versioned, and traceable.

Because monetization changes ship as config, you can verify them without touching app code:

  • CLI: validate and diff ./revturbine.playbook.json, or upload it as a draft and run preview plus evaluate --draft --user <file> before launch. The CLI reference lists the required selectors.
  • local_only: load a candidate revturbine.playbook.json in a test build and exercise the gates and placements against fixture users.
  • Debugging Decisions: use explainPlacementDecision() to see exactly why a decision resolved the way it did.