Suspend data limits: why courses lose bookmarks at 4 KB, and how to stay under

cmi.suspend_data is one string with a hard cap — 4,096 characters in SCORM 1.2, up to 64,000 in SCORM 2004 — and most platforms fail it silently. What the caps are per version and edition, how truncation shows up, and how to shrink what you store.

What suspend data is

SCORM gives a course exactly one place to store its own state between sessions: cmi.suspend_data, a single string. The bookmark element (lesson_location in 1.2, cmi.location in 2004) is tiny and meant for "which page"; everything else — quiz answers in progress, visited pages, branch decisions, video positions, shuffled question order — gets serialised into suspend data by the authoring tool or converter. The LMS stores the string verbatim and hands it back when the learner resumes. It has no idea what is inside it, and it does not promise to warn you when it will not fit.

The caps, by version and edition

SpecificationCap on cmi.suspend_data
SCORM 1.24,096 characters
SCORM 2004 2nd Edition4,000 characters
SCORM 2004 3rd / 4th Edition64,000 characters

Three practical notes. The 2004 2nd Edition cap is smaller than 1.2's — migrating a course "up" to 2004 can shrink its storage if the platform is 2nd Edition. Characters are not bytes: state stored as JSON with multi-byte characters can hit platform limits earlier than a character count suggests, because some LMSs enforce the limit on the stored byte length of their database column. And the cap applies to the whole string on every write — there is no appending; the course rewrites the full state each time.

How the failure actually looks

Almost no platform returns an error when the string is too long — the conformant response would be error 405 or a failed SetValue, but the common real-world behaviours are worse: silently truncating the string at the cap, or accepting it in the session and storing a truncated copy. Either way the failure appears one session later, in someone else's words: "the course forgot my progress", "it sent me back to the start", "my quiz answers disappeared halfway through". By then the truncated state often no longer parses (truncated JSON is invalid JSON), so the course falls back to a fresh start — which is why the symptom is usually a total reset rather than a partial one.

Because the failure is delayed and learner-specific, it does not show up in a quick author-side test of page one. It shows up when a learner gets far enough into the course for the state to outgrow the cap. The way to catch it before shipping is to measure: our conformance report shows peak suspend-data size against the cap for the target version (the check reads, for example, "3.1 KB of 64 KB"), and the free tester shows every write as it happens.

What courses put in there

Converted and authored courses typically store: the full visited-page map (often one entry per page, the biggest consumer in long courses), in-progress and submitted answers per question, question order for shuffled banks, media positions, and completion flags per section. A 90-page handbook conversion with a 25-question assessment sits naturally in the 3–6 KB range — fine for 2004 3rd/4th, over the line for 1.2. This is one of the five questions that should decide which SCORM version you build.

Staying under the cap

In descending order of effect:

Store less, not smaller. Drop per-page timestamps and redundant flags; a visited map plus current position reconstructs most of what long formats store. Completion of a linear section can be derived from position instead of stored per page.

Encode compactly. A JSON object with named keys ("{"page_12":{"visited":true}}") is several times the size of a bitfield or a compact positional string. Base64-packed bitfields for visited maps and answer states are the standard trick; some tools additionally compress before encoding.

Do not store what the LMS already stores. Score, status, location, and interactions have their own elements. Duplicating them in suspend data spends the budget twice.

Build for the right version. If measured state genuinely needs more than 4 KB and the destination platform supports 2004 3rd/4th Edition, build 2004 — that is the honest fix, not aggressive encoding.

Related: exit and entry

Suspend data only comes back if the attempt was suspended. In 1.2 the course must set cmi.core.exit to suspend before finishing (in 2004, cmi.exit, and a nav request of suspendAll); the LMS then reports entry as resume on the next launch and returns the stored string. Courses that leave exit empty end the attempt on some platforms — the suspend data is gone even though it was written correctly and was under the cap. When "lost progress" is not a size problem, it is nearly always this: an exit value problem. The full failure catalogue is in why SCORM completions go missing.

More from the spec library

Reference9 min The SCORM 2004 data model: every cmi element, and what changed from 1.2 A working reference for the SCORM 2004 run-time: the eight API functions, every data model element with its access and type, the twenty-four error codes, the adl.nav requests, and a complete 1.2 to 2004 mapping. Changelog1 min Changelog What changed in SCORM Central, newest first. Early-access releases are noted here as they land. Product reference3 min Runtime behaviour profiles: what each saved test profile asserts, and why A test profile is a saved set of LMS runtime behaviours — commit throttling, suspend-data enforcement, missing-score handling, status coercion — that the test suite replays a package against. What the dimensions are, what a pass means, and what it deliberately does not mean.

Start with one file.

Upload something you already have and see it as a package, with the conformance report and the runtime log alongside it.

→ upload  handbook.pdf
  parsing … 14 sections
  building manifest …
  validating … 0 errors, 2 notes
✓ handbook-scorm2004.zip
✓ preview link ready