Transactions
Group multiple write operations into an atomic unit — all succeed together or all roll back together.
Transactions work the same way on RushDB Cloud and on a self-hosted engine: the engine stages each write and applies them all at commit. Until then, nobody sees them, and reads in the transaction see the committed data. Records are named by id, and the engine resolves each id inside the transaction, so you can update, delete and link records created earlier in the same transaction.
Basic Pattern
- Python
- TypeScript
- shell
The idiomatic approach uses the context manager — auto-commits on success, auto-rolls back on exception:
# Context manager (recommended)
with db.tx.begin() as tx:
leo = db.records.create(label="ACTOR", data={"name": "Leonardo DiCaprio"}, transaction=tx)
inception = db.records.create(label="MOVIE", data={"title": "Inception"}, transaction=tx)
db.records.attach(source=leo, target=inception, options={"type": "ACTED_IN"}, transaction=tx)
# committed automatically — no explicit commit() needed
Or manually for more control:
tx = db.tx.begin()
try:
movie = db.records.create(label="MOVIE", data={"title": "Inception"}, transaction=tx)
actor = db.records.create(label="ACTOR", data={"name": "Leonardo DiCaprio"}, transaction=tx)
db.records.attach(source=movie, target=actor, options={"type": "STARS_IN"}, transaction=tx)
tx.commit()
except Exception:
tx.rollback()
raise
const tx = await db.tx.begin()
// optional: db.tx.begin({ ttl: 10_000 })
try {
const movie = await db.records.create({ label: 'MOVIE', data: { title: 'Dune', rating: 8.0 } }, tx)
const actor = await db.records.create({ label: 'ACTOR', data: { name: 'Timothée Chalamet' } }, tx)
await db.records.attach({ source: movie, target: actor, options: { type: 'STARS' } }, tx)
await tx.commit() // or: await db.tx.commit(tx)
} catch (e) {
await tx.rollback() // or: await db.tx.rollback(tx)
throw e
}
Pass tx as the last argument to any record or relationship method.
Use X-Transaction-Id header on any write endpoint:
# 1. Begin
TX_ID=$(curl -s -X POST https://api.rushdb.com/api/v1/tx \
-H "Authorization: Bearer $RUSHDB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ttl": 10000}' | jq -r '.data.id')
# 2. Create records
MOVIE_ID=$(curl -s -X POST https://api.rushdb.com/api/v1/records \
-H "Authorization: Bearer $RUSHDB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Transaction-Id: $TX_ID" \
-d '{"label": "MOVIE", "data": {"title": "Inception"}, "options": {"returnResult": true}}' | jq -r '.data.__id')
ACTOR_ID=$(curl -s -X POST https://api.rushdb.com/api/v1/records \
-H "Authorization: Bearer $RUSHDB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Transaction-Id: $TX_ID" \
-d '{"label": "ACTOR", "data": {"name": "Leonardo DiCaprio"}, "options": {"returnResult": true}}' | jq -r '.data.__id')
# 3. Link
curl -X POST https://api.rushdb.com/api/v1/relationships/$MOVIE_ID \
-H "Authorization: Bearer $RUSHDB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Transaction-Id: $TX_ID" \
-d '{"targetIds": "'$ACTOR_ID'", "type": "STARS_IN"}'
# 4. Commit
curl -X POST https://api.rushdb.com/api/v1/tx/$TX_ID/commit \
-H "Authorization: Bearer $RUSHDB_API_KEY"
API Reference
- Python
- TypeScript
- shell
| Method | Description |
|---|---|
db.tx.begin(ttl?) as ctx mgr | Start transaction, auto-commit/rollback on scope exit |
db.tx.begin(ttl?) | Start a new transaction; returns a Transaction object |
tx.commit() | Persist all operations |
tx.rollback() | Discard all operations |
| Method | Description |
|---|---|
db.tx.begin({ ttl? }) | Start a transaction. Returns a Transaction with .id |
db.tx.get(tx) | Check if a transaction still exists (returns 404 if expired) |
db.tx.commit(tx) | Commit — makes all changes permanent |
db.tx.rollback(tx) | Rollback — discards all changes |
tx.commit() | Shorthand on the transaction object itself |
tx.rollback() | Shorthand on the transaction object itself |
| Endpoint | Description |
|---|---|
POST /api/v1/tx | Begin transaction. Returns { id } |
GET /api/v1/tx/:txId | Check if transaction still exists |
POST /api/v1/tx/:txId/commit | Commit — makes all changes permanent |
POST /api/v1/tx/:txId/rollback | Rollback — discards all changes |
Add X-Transaction-Id: $TX_ID to any create, update, delete, or relationship request.
Timeouts
Uncommitted transactions are automatically rolled back after the TTL expires.
| Parameter | RushDB Cloud | Self-hosted engine |
|---|---|---|
| Default TTL | 5 000 ms | transactions.default-ttl-seconds (60 s) |
| Maximum TTL | 55 000 ms | transactions.max-age-seconds (60 s); a larger ttl is capped |
autocommit: true commits a transaction whose TTL elapses instead of discarding it.
- Python
- TypeScript
- shell
tx = db.tx.begin(ttl=15000) # 15 s timeout
const tx = await db.tx.begin({ ttl: 15_000 }) // 15 s timeout
curl -X POST https://api.rushdb.com/api/v1/tx \
-H "Authorization: Bearer $RUSHDB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ttl": 15000}'
| Field | Type | Description |
|---|---|---|
ttl | number | TTL in ms. Default: 5000. Max: 55000 |
autocommit | boolean | Commit instead of rolling back when the TTL elapses. Default: false |
Supported Operations
| Category | Staged in a transaction |
|---|---|
| Records | create · update · set · delete_by_id / deleteById |
| Relationships | attach |
| Imports | import_json / importJson · import_csv / importCsv (they report counts, not records, until commit) |
These writes are refused inside a transaction, because the engine cannot stage them: deleting records by query (delete), detach, relationships.createMany / deleteMany, upserts and merge imports, writes with inline vectors, and property deletes. RushDB Cloud answers them with 400 Bad Request and rolls the transaction back; in direct mode the SDK throws DirectModeError before sending anything. Run them outside the transaction.
Reads (find, findById, …) see committed data, not the transaction's staged writes. A staged write returns its record as the transaction sees it.
A commit can fail with a conflict when another commit changed a record this transaction wrote; RushDB Cloud returns 409 Conflict. Begin a new transaction and retry. See Transactions in the engine manual for isolation and retry details.
See also
- Store Records — in-transaction create, update, delete examples
- Connect Records — in-transaction attach, detach examples
- Find & Query — in-transaction read examples
- TypeScript Transaction type