Menu

SQLite Savepoints: Nested Transactions with ROLLBACK TO

How savepoints work in SQLite — named markers inside a transaction you can roll back to without throwing the whole thing away.

This page includes runnable editors — edit, run, and see output instantly.

A Savepoint Is a Named Bookmark Inside a Transaction

A regular transaction is all-or-nothing: everything between BEGIN and COMMIT either lands together or gets thrown out together. That's usually what you want — but sometimes you'd like a finer grain. "Try this batch of changes; if it goes wrong, undo just that batch and keep the rest of the transaction alive."

That's what a savepoint is. You drop a named bookmark, do some work, and then either keep the work (RELEASE) or rewind to the bookmark (ROLLBACK TO).

Ada's debit and Boris's credit both stick. The mistaken update to Nobody was rolled back without losing the rest of the transaction.

The Three Commands

Three statements is the whole API:

  • SAVEPOINT name — set a bookmark.
  • RELEASE SAVEPOINT name — keep the work done since the bookmark; remove the bookmark.
  • ROLLBACK TO SAVEPOINT name — undo everything since the bookmark; the bookmark stays in place so you can try again.

The word SAVEPOINT after RELEASE and ROLLBACK TO is optional — RELEASE risky and ROLLBACK TO risky both work.

The step 2 attempt row never existed as far as the final database is concerned. Everything else lands.

Savepoints Without an Outer Transaction

Here's a small twist: you can issue SAVEPOINT without a BEGIN first. SQLite quietly opens a transaction for you, and the outermost savepoint plays the role of the transaction itself. RELEASE on that savepoint commits, ROLLBACK TO rewinds without committing.

That's why savepoints are sometimes described as "named transactions." But mixing the two styles in real code gets confusing — pick one. Most people use explicit BEGIN ... COMMIT for the outer boundary and savepoints only for the inner partial-undo points.

Nesting Savepoints

Savepoints stack. You can set one inside another and roll the inner one back without touching the outer:

Final contents: a, b, d. Rolling back to inner removed c but left the work done before inner (the insert of b) intact, and the transaction kept going.

Rolling back to an outer savepoint also discards anything done at inner levels — the whole stack above that name unwinds at once:

Both b and c are gone. ROLLBACK TO outer rewinds everything since outer was set, including inner and the c insert.

Why Use Savepoints?

The classic case is processing a batch where individual items are allowed to fail without scrapping the whole batch. Wrap each item in a savepoint; if it fails, roll back to the savepoint and move on:

In real application code, the bad insert raises an error and the application catches it, issues ROLLBACK TO, and continues. Two good rows land; the bad row doesn't poison the batch.

This pattern is also how ORMs and migration tools implement nested transactions — they don't actually nest BEGIN blocks (SQLite doesn't allow that), they map nested calls to savepoints.

A Few Things to Watch

A handful of details that bite people new to savepoints:

  • COMMIT always commits the whole transaction. It doesn't matter how many open savepoints you have — COMMIT (or its alias END) closes the entire outer transaction. Don't think of RELEASE as a partial commit; nothing is durable until the surrounding transaction commits.
  • ROLLBACK (without TO) aborts everything. It ends the transaction and discards all open savepoints. Use ROLLBACK TO name when you want to keep the transaction alive.
  • A savepoint stays open until released or rolled back through. Forgetting to RELEASE doesn't lose data, but the bookmark just sits there until the transaction ends.
  • Names aren't required to be unique. If you set SAVEPOINT s twice, ROLLBACK TO s finds the most recent one. Useful for recursion; confusing if accidental.

Next: Views

Savepoints give you finer control over writes. The next step is shaping how you read — saving a query as a named, reusable object you can SELECT from like a table. That's a view, and it's coming up next.

Frequently Asked Questions

What is a savepoint in SQLite?

A savepoint is a named marker you set inside a transaction. Later you can ROLLBACK TO that name to undo everything done after it, or RELEASE it to keep the changes and discard the marker. Savepoints let you treat parts of a transaction as smaller, recoverable units.

What's the difference between a savepoint and a transaction in SQLite?

A transaction starts with BEGIN and ends with COMMIT or ROLLBACK. A savepoint is set inside a transaction with SAVEPOINT name and gives you a partial undo point. Rolling back to a savepoint doesn't end the surrounding transaction — you can keep working and commit later.

Can SQLite savepoints be nested?

Yes. You can stack savepoints with different names, and ROLLBACK TO outer undoes everything down to that level, including any inner savepoints. Names don't have to be unique — SQLite uses the most recent savepoint with that name, which is the standard stack behavior.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED