Skip to content

Runtime Modes

Two modes matter for most apps: local and hosted. A third, custom_endpoints, routes selected context and telemetry calls through your own proxy while Playbook delivery stays with RevTurbine.

Hosted mode is how you change monetization without a deploy. RevTurbine stores and versions your Playbook; the SDK in your app keeps a fresh local copy and decides from it.

What it gives you:

  • Change without deploying. Edit plans, entitlements, targeting and prompts in the RevTurbine dashboard, with your coding agent, or through the CLI. Draft, review, launch. The SDK picks up the new release on its next refresh.
  • Versioned Playbooks. Every launch is an immutable Release with history. Roll back by restoring any earlier one.
  • Analytics. Conversion and usage analytics, so you can see what’s working. Growth adds deeper analytics and self-driving growth recommendations.
  • Signals your app doesn’t hold. Billing status from Stripe, trial state, per-customer exceptions and end-user behavior follow the user. Caps and cooldowns hold across devices, and an exception applies wherever that user shows up.

What doesn’t change: 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. Hosted mode changes where the Playbook and user state come from, not where decisions run. We add no latency, and our availability never affects your product.

In code: runtimeMode: RuntimeMode.Server (revturbine_server).

Local mode ships the Playbook with your app. You version it in your own repo, and changing it is a deploy. No account, always free, and production-capable on its own. Every decision is made the same way as in hosted mode.

In code: runtimeMode: RuntimeMode.LocalOnly (local_only) with localRuntime: { playbook }.

  1. Getting started, building a demo, or shipping a Playbook that rarely changes? Local.
  2. Want to change monetization without deploying, see analytics, or set per-customer exceptions? Hosted.
  3. Need context or telemetry calls to go through your own proxy? Hosted, with custom_endpoints.
ModeWhere the Playbook comes fromWhat RevTurbine providesRequired config
Local (local_only)Bundled with your appNothing at runtime; optional anonymous adoption beaconlocalRuntime: { playbook }
Hosted (revturbine_server)RevTurbine, cached locally and refreshed in the backgroundPlaybook delivery and versioning; user state (billing, trials, exceptions, behavior); analyticstenantId, publicKey, endpoint
Hosted with custom endpoints (custom_endpoints)RevTurbine, cached locally as in hosted modeSame as hosted; selected context and telemetry calls use your endpointsHosted config + endpointOverrides

Use a Playbook checked into your app for local mode, or let the SDK retrieve the launched Playbook from RevTurbine in hosted mode. Pass the validated artifact intact. An app endpoint that reshapes, filters or strips fields creates a different artifact from the one you validated.

endpointOverrides does not reroute Playbook delivery. Keep endpoint set to RevTurbine and override only the supported context and telemetry calls. See the endpoint reference for the complete list.

In every mode the SDK evaluates entitlements and placements inside your app, from the Playbook it holds. No check and no placement decision makes a network call.

In revturbine_server mode the SDK fetches the launched Playbook at init, keeps it in memory, and re-checks for a new release at most once a minute — a launched Playbook is immutable per version, so polling more often would only waste requests. If a refresh fails, the SDK keeps the last-known-good Playbook and never throws. Before the first Playbook has arrived, an entitlement check denies with an infrastructure reason (config_unavailable) rather than guessing.

Set the mode with the typed RuntimeMode constant rather than a raw string:

TypeScript
import { RuntimeMode } from '@revturbine/sdk';
// runtimeMode: RuntimeMode.LocalOnly | RuntimeMode.Server | RuntimeMode.CustomEndpoints

local_only makes no config or decisioning calls and does not send clickstream events to RevTurbine ingest. A keyless, anonymous sdk_init adoption beacon is the one network exception. Set anonymousTelemetry: false (or previewMode: true for docs and examples) when the process must make zero RevTurbine requests.

TypeScript
import { initRevTurbine, RuntimeMode } from '@revturbine/sdk';
import playbook from './revturbine.playbook.json';
// No account, key, tenant or endpoint: the Playbook is the whole configuration.
const session = await initRevTurbine({
runtimeMode: RuntimeMode.LocalOnly,
localRuntime: {
playbook,
storageKey: 'my-app:revturbine-local-runtime',
},
});

Local mode needs no placeholder tenant, API key or endpoint. Add a user when your rules depend on identity or plan, resolve the CTA action types your Playbook authors, and optionally supply branding:

TypeScript
import { initRevTurbine, RuntimeMode } from '@revturbine/sdk';
import playbook from './revturbine.playbook.json';
const session = await initRevTurbine({
runtimeMode: RuntimeMode.LocalOnly,
localRuntime: { playbook },
user: { id: 'user_123', plan_handle: 'starter' },
uiPathResolvers: {
navigate_to_plans: () => { window.location.assign('/pricing'); },
},
branding: {
workspace_name: 'My app',
theme: { colors: { primary: '#6366f1' } },
},
});
// The async initializer returns a session; instance-only methods live on .sdk.
const branding = session.sdk.getBranding();

Use your actual plan handle and CTA action types. Branding is optional and merges over defaults. With React, pass the same options to RevTurbineProvider and let it initialize the SDK. See User Context, CTA actions and Theming for the individual options.

When you want dashboard-managed changes without deploying your app, switch the connection options. Local mode is also production-capable; your component code stays the same:

<RevTurbineProvider
options={{
runtimeMode: RuntimeMode.LocalOnly,
localRuntime: { playbook },
tenantId: process.env.REVTURBINE_TENANT_ID!,
publicKey: process.env.REVTURBINE_PUBLIC_KEY!,
runtimeMode: RuntimeMode.Server,
user: { id: 'user_123', plan_handle: 'starter' },
}}
>

Providers are for teams that supply their own facts — entitlement grants, user context — from more than one source. They are not a resilience mechanism for revturbine_server mode: decisions are evaluated locally from the cached Playbook, so RevTurbine’s availability never affects them. Most apps configure no provider.

Available options:

  • provider: primary provider.
  • providerFallbacks: ordered fallback provider list.
  • providerFailureSlotBehavior: 'invisible' (default) or 'placeholder'.

Behavior:

  1. SDK calls primary provider first.
  2. If primary fails, SDK logs a warning and executes fallbacks in order.
  3. If all configured providers fail for a method, slots render hidden or placeholder output based on providerFailureSlotBehavior.
  1. Start with local_only to validate your integration and placement slots.
  2. For dashboard-managed changes and analytics, switch to RuntimeMode.Server and provide real credentials.
  3. Re-check billing-critical actions on your server with the same Playbook — see Server-Side Integration.
  4. If you supply your own facts through providers, choose providerFailureSlotBehavior per surface.