Transactions

The SQLSpec plugin supports two transaction modes: autocommit and manual commit. Choose the mode that fits your application’s error handling and rollback requirements.

Commit Modes

Autocommit (default)

Each statement commits automatically. Use this for read-heavy workloads or when you don’t need atomic multi-statement operations.

Manual Commit

You control when to commit or rollback. Use this for write operations that must succeed or fail together.

commit modes
from sqlspec import SQLSpec
from sqlspec.adapters.sqlite import SqliteConfig
from sqlspec.extensions.litestar import CommitMode, SQLSpecPlugin

sqlspec = SQLSpec()
sqlspec.add_config(
    SqliteConfig(
        connection_config={"database": ":memory:"},
        extension_config={"litestar": {"commit_mode": CommitMode.autocommit}},
    )
)
sqlspec.add_config(
    SqliteConfig(
        connection_config={"database": ":memory:"},
        extension_config={"litestar": {"commit_mode": CommitMode.manual}},
    ),
    name="manual",
)

plugin = SQLSpecPlugin(sqlspec=sqlspec)

Rollback on Error

In manual mode, uncaught exceptions trigger an automatic rollback before the response is sent. This keeps your database consistent when handlers fail.

@post("/transfer")
async def transfer(db: AsyncSession, data: TransferRequest) -> dict:
    await db.execute("UPDATE accounts SET balance = balance - :amount WHERE id = :from_id",
                     {"amount": data.amount, "from_id": data.from_account})
    await db.execute("UPDATE accounts SET balance = balance + :amount WHERE id = :to_id",
                     {"amount": data.amount, "to_id": data.to_account})
    await db.commit()  # Both updates succeed or both rollback
    return {"status": "transferred"}

Nested Transactions

Use savepoints for nested transaction scopes. SQLSpec translates begin_nested() to savepoints on databases that support them.