Architecture
How the SDK, ingestion API, and dashboard fit together — and what happens to a session from capture to display.
Three moving parts: an SDK inside your product, an ingestion API, and a
dashboard. There are two SDKs — @scalebun/react-native and @scalebun/web —
and they are separate implementations of the same contract, sharing a backend, a
dashboard and one unified session model.
The path data takes#
flowchart TD
A["Your app<br/>@scalebun/react-native"] -->|"batched envelopes"| B["Ingestion API"]
W["Your website<br/>@scalebun/web"] -->|"batched envelopes"| B
A -->|"GET /v1/config"| C["Runtime config<br/>flags · rollouts · experiments"]
W -->|"GET /v1/config"| C
B --> D[("Storage")]
D --> E["Dashboard<br/>Monitor · Diagnose · Analyze · Engage"]
C -.->|"entitlements"| A
C -.->|"entitlements"| WInside the SDK#
Neither SDK is a single pipeline — each runs several independent capture lanes, and any lane can be switched off without affecting the others:
| Lane | React Native | Web |
|---|---|---|
| Session | The unified session record and its lifecycle | Same, keyed to the browser session |
| Journey | Screens, taps, scrolls, navigation | Routes, clicks, scrolls, form interactions |
| Replay | Frames and breadcrumbs | DOM reconstruction, not screenshots |
| Performance | App launch, screen load, network timing, frame metrics | Web Vitals, page load, SPA route transitions, LoAF |
| Crash | Native crashes, JS errors, ANRs | ReportingObserver and session-liveness recovery |
| Network | Request and response metadata, with redaction | fetch, XHR, WebSocket, SSE, with redaction |
| Engage | In-app messages, surveys, NPS, ratings, push | The same, plus Web Push and coachmarks |
Every lane writes into a shared outbox rather than calling the network directly. The outbox batches, persists to disk, retries with backoff, and drains when connectivity returns — which is why the SDK works offline and why no capture call ever blocks your UI.
Authentication#
The SDK authenticates with a client key. Server-to-server calls use a secret key.
| Header | Used by | Purpose |
|---|---|---|
x-scalebun-client-key | SDK, in-app | Identifies the app environment. Safe to ship. |
x-scalebun-secret-key | Server-to-server | Privileged operations. Never in an app. |
x-scalebun-signature | SDK, optional | HMAC-SHA256(rawBody, clientKey), hex-encoded. |
The signature header is optional by design: requests without it are accepted and simply not marked signature-verified, so older SDK versions keep working after a backend upgrade.
Tenancy#
Everything is scoped along one chain:
Organization → Project → App → AppEnvironment → SdkKey
Each environment carries its own key pair, which is what keeps development traffic
out of production data. A disabled app or environment rejects ingestion with
401.
Client keys are prefixed so a key visibly declares its blast radius:
| Prefix | Environment |
|---|---|
skb_test_ck_… | Development |
skb_staging_ck_… | Staging |
skb_live_ck_… | Production |
Keys issued before the prefixed scheme (scalebun_ck_…) remain valid.
Runtime configuration#
The SDK fetches configuration at startup and caches it. That single payload drives feature flags, rollouts, experiment assignment, and entitlements — which capabilities your organization is allowed to use.
Entitlements are applied before a collector is even registered. If your plan does not include session replay, the replay lane is never started, so it generates no traffic and costs nothing. The server also rejects data for a disabled capability, so this is an optimisation rather than the security boundary.
Related#
Core concepts — sessions, identity, events, envelopes.
Configuration — every option, generated from source.
API — the endpoint reference.