{
  "slug": "sqlite-savepoint",
  "term": "SQLite savepoint",
  "aliases": [
    "SAVEPOINT",
    "ROLLBACK TO",
    "RELEASE SAVEPOINT"
  ],
  "definition": "A SQLite savepoint is a named transaction-stack boundary that permits partial rollback without necessarily ending the surrounding transaction.",
  "note": "SAVEPOINT can start an outer transaction or mark a point inside one. RELEASE removes the newest matching savepoint and any younger marks. Releasing an inner mark is not an independent commit: a later outer ROLLBACK can still undo its writes. ROLLBACK TO restores the database to the target savepoint state, removes younger marks and retains the target for reuse. A successful RELEASE that empties the transaction stack commits. Names need not be unique. [savepoints]\n\nBEGIN transactions do not nest. After an execution error, check the actual transaction state rather than assuming the enclosing transaction survived. [transactions] [autocommit]\n\nFour constructed cases run in both DELETE and WAL modes using explicit SQL through Python sqlite3. The row inserted inside the nested savepoint remained invisible to a second connection and disappeared after outer rollback; outermost RELEASE made it visible to that drained autocommit observer. Complete ordered steps and normal reopen results are available for replay. This is not a power-loss test. [experiment]\n\nCommit and WAL checkpoint progress are separate. An inner RELEASE is not evidence of either outer completion or history reclamation. [wal]\n\nOutermost RELEASE does not refresh an existing WAL reader snapshot. In a two-case control, a reader that executed BEGIN and SELECT before release kept its old rows until ending the transaction; a fresh connection saw the committed row. BEGIN without an early read did not acquire the old snapshot. [isolation] [reader-control]\n\nDo not transfer savepoint lifetime rules between systems. ARIES section 5.2 consumes a rollback target, while SQLite retains it. This comparison concerns contracts, not an assertion that SQLite implements ARIES. [aries]",
  "related": [
    "sqlite-transaction-state",
    "sqlite-wal-end-mark",
    "checkpoint-starvation"
  ],
  "citations": [
    {
      "id": "savepoints",
      "title": "SQLite: Savepoints, nesting and transaction-stack rules",
      "url": "https://www.sqlite.org/lang_savepoint.html",
      "accessed": "2026-11-13"
    },
    {
      "id": "transactions",
      "title": "SQLite: Transactions and response to errors",
      "url": "https://www.sqlite.org/lang_transaction.html",
      "accessed": "2026-11-13"
    },
    {
      "id": "autocommit",
      "title": "SQLite C API: Test For Auto-Commit Mode",
      "url": "https://www.sqlite.org/c3ref/get_autocommit.html",
      "accessed": "2026-11-13"
    },
    {
      "id": "wal",
      "title": "SQLite: Write-Ahead Logging, commit and checkpoint",
      "url": "https://www.sqlite.org/wal.html#how_wal_works",
      "accessed": "2026-11-13"
    },
    {
      "id": "experiment",
      "title": "Hesela: eight SQLite savepoint schedules, complete observations",
      "url": "https://hesela.dev/research/sqlite-savepoint/results.json",
      "accessed": "2026-11-13"
    },
    {
      "id": "analysis",
      "title": "Hesela: SQLite savepoint release versus transaction completion",
      "url": "https://hesela.com/analyses/sqlite-wal-checkpoint-starvation/#savepoint-boundaries",
      "accessed": "2026-11-13"
    },
    {
      "id": "isolation",
      "title": "SQLite: Isolation, WAL snapshots and read-transaction lifetime",
      "url": "https://www.sqlite.org/isolation.html",
      "accessed": "2026-11-13"
    },
    {
      "id": "reader-control",
      "title": "Hesela: WAL savepoint release and retained-reader control",
      "url": "https://hesela.dev/research/sqlite-savepoint/reader-snapshot.json",
      "accessed": "2026-11-13"
    },
    {
      "id": "aries",
      "title": "Mohan et al. ARIES. ACM TODS 17(1), 94-162 (1992), section 5.2, pp. 117-118. DOI 10.1145/128765.128770.",
      "url": "https://www.cs.cmu.edu/~natassa/courses/15-721/papers/p94-mohan.pdf",
      "accessed": "2026-11-13"
    }
  ],
  "status": "shipping",
  "advantages": [],
  "limitations": [
    "A savepoint is not an independently durable nested transaction or a backup."
  ],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-11-13",
  "provenance": [
    "Source synthesis plus deterministic SQL fixtures on the recorded runtime; no crash, I/O-fault or physical-persistence experiment."
  ]
}
