Runtime Transactions
Use runtime transactions when a service must keep several writes consistent.Public helpers
The root package now exposes:transaction(connectionName, work, options?)lockedTransaction(connectionName, lockKey, work, options?)model.withTransaction(work, options?)
SQL transaction example
Transaction-bound model helpers
UseModel.useTransaction(tx) when you want ORM reads and writes to stay inside the active transaction.
forUpdate()andforShare()are available only on transaction-bound SQL findersskipLocked()requiresforUpdate()orforShare()first- PostgreSQL:
FOR UPDATE,FOR SHARE,SKIP LOCKED - MySQL:
FOR UPDATE,FOR SHARE,SKIP LOCKED - SQLite: row-lock helpers are rejected
- MongoDB: row-lock helpers are rejected
- raw
tx.execute(...)remains available for advanced SQL paths
- a model already bound to
txmay call.useTransaction(tx)again as a no-op - rebinding that model to a different transaction on the same connection fails fast
- hydrated finder results keep the active transaction/session for later
save()/delete()calls
SQL locking example
UselockedTransaction(...) when one critical section must serialize concurrent writers.
- PostgreSQL: advisory transaction lock
- MySQL: named lock + SQL transaction
- SQLite: no
lockedTransaction(...)helper - MongoDB: no
lockedTransaction(...)helper
Mongo transaction example
- the helper exposes
db,session, andcollection(name) - each write must pass
{ session: tx.session } - multi-document transactions still require a transaction-capable Mongo deployment
Model-owned convenience helper
withTransaction(...) is a convenience wrapper over the model’s configured connectionName.
Practical rule
- keep transaction orchestration in services
- use
transaction(...)for grouped writes - use
lockedTransaction(...)only for real race-sensitive flows - do not put transaction control in controllers