LRS and telemetry operations¶
Production runbook for xAPI delivery, analytics batching, and observability hooks. For React wiring, see deployment guide and production checklist.
Architecture¶
Browser SPA
├─ track() → batchSink → your analytics API (VITE_ANALYTICS_URL proxy)
└─ xAPI transport → your LRS proxy (VITE_XAPI_PROXY_URL)
└─ optional: LRS (never embed LRS passwords in the SPA)
Rule: The browser calls your backend proxies, not a public LRS with embedded credentials. Use short-lived tokens minted server-side.
Backend proxy pattern¶
// courseConfig.ts (production)
import { createFetchTransport, createFetchBatchSink } from "@lessonkit/xapi";
const xapiFetch = createFetchTransport({
url: import.meta.env.VITE_XAPI_PROXY_URL,
timeoutMs: 30_000,
headers: () => ({ Authorization: `Bearer ${getSessionToken()}` }),
});
const analytics = createFetchBatchSink({
url: import.meta.env.VITE_ANALYTICS_URL,
timeoutMs: 30_000,
});
Your proxy validates the learner session, attaches LRS Basic auth or OAuth server-side, and forwards statements to the LRS.
Statement lifecycle¶
Emit — React provider maps telemetry → xAPI via
telemetryEventToXAPIStatementQueue — Failed or async sends land in an in-memory queue (default max 1000)
Retry —
createFetchTransportretries with exponential backoffPagehide —
exitTransport/exitBatchSinkusekeepalivefetch where supportedCap — Oldest statement dropped when queue is full →
onXapiQueueCapDead letter — After repeated head failures, statements may persist via
persistDeadLetterStatement(see xAPI reference — dead letter)
Observability hooks matrix¶
Hook |
When it fires |
Required when |
|---|---|---|
|
Transport fails after retries |
xAPI delivery enabled in production |
|
Queue size changes |
Recommended when xAPI enabled |
|
Queue exceeded max size |
Recommended when xAPI enabled |
|
Analytics sink throws |
Tracking enabled with custom sink |
|
Batch sink throws |
Batch tracking enabled |
|
Bridge call blocked (allowlist) |
|
See production checklist for the full matrix.
LRS outage runbook (24h+)¶
Phase |
Learner experience |
Your action |
|---|---|---|
0–5 min |
Statements queue; UI works |
Monitor |
5–60 min |
Queue grows; retries continue |
Alert on |
Cap reached |
Oldest statements dropped |
|
Recovery |
New statements deliver |
Export |
Analytics batching uses the same pattern with onBatchSinkError and batch queue depth if you implement custom monitoring.
cmi5 and AU launch¶
cmi5 packages include launch parameters for the LRS. Staging-test cmi5 the same way as SCORM — see LMS compatibility. Activity IRIs must match lessonkit.json → tracking.xapi.activityIri.
Security checklist¶
LRS credentials only on the server
assertSafeLrsUrlor equivalent in custom transportsHTTPS only for proxy endpoints in production
Token TTL aligned with session length
Log statement IDs, not learner PII, in proxy logs