Transactions
Manage ACID transactions using ekoDB's REST API with support for multiple isolation levels, savepoints, and full rollback capabilities.
:::tip Architecture & Concepts For detailed information about transactions architecture, isolation levels, and best practices, see the Transactions Architecture Reference. :::
:::warning REST API Transaction Considerations When using the REST API directly (without client libraries), be aware of these important limitations:
- Manual Transaction ID Management - You must track and include the
transaction_idwith every operation within a transaction - Connection Stateless - REST is stateless; transaction state is maintained server-side with timeout expiration
- No Automatic Rollback - If your client crashes, the transaction will remain pending until timeout (default: 5 minutes)
- Network Failures - A failed commit response doesn't guarantee the commit failed; use idempotency keys for critical operations
Recommendation: Use the official client libraries which handle transaction lifecycle automatically. :::
Isolation Levels
ekoDB supports four standard SQL isolation levels:
- ReadUncommitted - Highest performance, dirty reads allowed
- ReadCommitted (default) - Good balance of performance and consistency
- RepeatableRead - Consistent reads within transaction
- Serializable - Highest consistency, full MVCC
Begin Transaction
Start a new transaction with optional isolation level and timeout.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
let tx_id = client.begin_transaction(Some(TransactionOptions {
isolation_level: IsolationLevel::Serializable,
timeout_seconds: Some(600),
})).await?;
println!("{}", tx_id); // 'tx-abc-123'
tx_id = await client.begin_transaction(
isolation_level='Serializable'
)
print(tx_id) # 'tx-abc-123'
const txId = await client.beginTransaction({
isolation_level: 'Serializable'
});
console.log(txId); // 'tx-abc-123'
const txId = await client.beginTransaction({
isolation_level: 'Serializable'
});
console.log(txId); // 'tx-abc-123'
val txId = client.beginTransaction(
isolationLevel = "Serializable"
)
println(txId) // 'tx-abc-123'
txId, err := client.BeginTransaction(ekodb.TransactionOptions{
IsolationLevel: "Serializable",
})
fmt.Println(txId) // 'tx-abc-123'
curl -X POST https://{EKODB_API_URL}/api/transactions \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"isolation_level": "Serializable",
"timeout_seconds": 600
}'
# Response
{
"transaction_id": "tx-abc-123",
"isolation_level": "Serializable",
"created_at": 1699814400
}
:::info Working Examples Prefer a client library? See examples in Rust, Python, TypeScript, Go, or Kotlin
Want to use the REST API directly? See examples in JavaScript, Python, Go, or Rust :::
Parameters:
isolation_level(optional) -ReadUncommitted,ReadCommitted,RepeatableRead,Serializabletimeout_seconds(optional) - Default: 300 (5 minutes)
Commit Transaction
Commit all operations within the transaction.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
client.commit_transaction(&tx_id).await?;
await client.commit_transaction(tx_id)
await client.commitTransaction(txId);
await client.commitTransaction(txId);
client.commitTransaction(txId)
err := client.CommitTransaction(txId)
curl -X POST https://{EKODB_API_URL}/api/transactions/{transaction_id}/commit \
-H "Authorization: Bearer {YOUR_API_TOKEN}"
# Response
{
"status": "committed",
"transaction_id": "tx-abc123",
"operations_count": 5
}
Rollback Transaction
Rollback all operations and abort the transaction.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
client.rollback_transaction(&tx_id).await?;
await client.rollback_transaction(tx_id)
await client.rollbackTransaction(txId);
await client.rollbackTransaction(txId);
client.rollbackTransaction(txId)
err := client.RollbackTransaction(txId)
curl -X POST https://{EKODB_API_URL}/api/transactions/{transaction_id}/rollback \
-H "Authorization: Bearer {YOUR_API_TOKEN}"
# Response
{
"status": "rolled_back",
"transaction_id": "tx-abc123",
"operations_rolled_back": 5
}
Create Savepoint
Create a savepoint for partial rollback within a transaction.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
client.create_savepoint(&tx_id, "checkpoint1").await?;
await client.create_savepoint(tx_id, 'checkpoint1')
await client.createSavepoint(txId, 'checkpoint1');
await client.createSavepoint(txId, 'checkpoint1');
client.createSavepoint(txId, "checkpoint1")
err := client.CreateSavepoint(txId, "checkpoint1")
curl -X POST https://{EKODB_API_URL}/api/transactions/{transaction_id}/savepoints \
-H "Authorization: Bearer {ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "checkpoint1"
}'
# Response
{
"status": "created",
"transaction_id": "tx-abc123",
"savepoint_name": "checkpoint1"
}
Rollback to Savepoint
Rollback to a specific savepoint, undoing operations after it.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
client.rollback_to_savepoint(&tx_id, "checkpoint1").await?;
await client.rollback_to_savepoint(tx_id, 'checkpoint1')
await client.rollbackToSavepoint(txId, 'checkpoint1');
await client.rollbackToSavepoint(txId, 'checkpoint1');
client.rollbackToSavepoint(txId, "checkpoint1")
err := client.RollbackToSavepoint(txId, "checkpoint1")
curl -X POST https://{EKODB_API_URL}/api/transactions/{transaction_id}/savepoints/{savepoint_name}/rollback \
-H "Authorization: Bearer {ADMIN_TOKEN}"
# Response
{
"status": "rolled_back",
"transaction_id": "tx-abc123",
"savepoint_name": "checkpoint1",
"operations_rolled_back": 3
}
Release Savepoint
Remove a savepoint that's no longer needed.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
client.release_savepoint(&tx_id, "checkpoint1").await?;
await client.release_savepoint(tx_id, 'checkpoint1')
await client.releaseSavepoint(txId, 'checkpoint1');
await client.releaseSavepoint(txId, 'checkpoint1');
client.releaseSavepoint(txId, "checkpoint1")
err := client.ReleaseSavepoint(txId, "checkpoint1")
curl -X DELETE https://{EKODB_API_URL}/api/transactions/{transaction_id}/savepoints/{savepoint_name} \
-H "Authorization: Bearer {ADMIN_TOKEN}"
# Response
{
"status": "released",
"transaction_id": "tx-abc123",
"savepoint_name": "checkpoint1"
}
Get Transaction Status
Check the current status of a transaction.
- Client Libraries (Recommended)
- Direct API
- 🦀 Rust
- 🐍 Python
- 📘 TypeScript
- 📦 JavaScript
- 🟣 Kotlin
- 🔷 Go
let status = client.get_transaction_status(&tx_id).await?;
println!("{:?}", status);
status = await client.get_transaction_status(tx_id)
print(status['state'])
print(status['operations_count'])
const status = await client.getTransactionStatus(txId);
console.log(status.state);
console.log(status.operations_count);
const status = await client.getTransactionStatus(txId);
console.log(status.state);
console.log(status.operations_count);
val status = client.getTransactionStatus(txId)
println(status)
status, err := client.GetTransactionStatus(txId)
fmt.Println(status)
curl https://{EKODB_API_URL}/api/transactions/{transaction_id} \
-H "Authorization: Bearer {ADMIN_TOKEN}"
# Response
{
"transaction_id": "tx-abc123",
"state": "Active",
"isolation_level": "Serializable",
"operations_count": 5,
"savepoints_count": 2,
"created_at": 1699814400,
"last_activity": 1699814450,
"timeout_seconds": 600
}
List Active Transactions
List all currently active transactions.
- Client Libraries (Recommended)
- Direct API
- 📘 TypeScript
- 📦 JavaScript
- 🐍 Python
- 🦀 Rust
- 🟣 Kotlin
- 🔷 Go
const transactions = await client.listActiveTransactions();
console.log(transactions);
/*
[
{ transaction_id: 'tx-abc-123', isolation_level: 'Serializable', created_at: 1699814400 },
{ transaction_id: 'tx-def-456', isolation_level: 'ReadCommitted', created_at: 1699814500 }
]
*/
const transactions = await client.listActiveTransactions();
console.log(transactions);
transactions = await client.list_active_transactions()
print(transactions)
# [{'transaction_id': 'tx-abc-123', ...}]
let transactions = client.list_active_transactions().await?;
println!("{:?}", transactions);
val transactions = client.listActiveTransactions()
println(transactions)
transactions, err := client.ListActiveTransactions()
fmt.Println(transactions)
curl https://{EKODB_API_URL}/api/transactions \
-H "Authorization: Bearer {ADMIN_TOKEN}"
# Response
{
"transactions": [
{
"transaction_id": "tx-abc123",
"state": "Active",
"isolation_level": "Serializable",
"operations_count": 5,
"savepoints_count": 2,
"created_at": 1699814400,
"last_activity": 1699814450,
"timeout_seconds": 600
},
{
"transaction_id": "tx-def456",
"state": "Active",
"isolation_level": "ReadCommitted",
"operations_count": 2,
"savepoints_count": 0,
"created_at": 1699814500,
"last_activity": 1699814510,
"timeout_seconds": 300
}
],
"count": 2
}
Complete Example
Here's a complete example of a multi-step transaction with savepoints:
# 1. Begin transaction
curl -X POST https://{EKODB_API_URL}/api/transactions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{"isolation_level": "Serializable", "timeout_seconds": 600}'
# Response: {"transaction_id": "tx-001"}
# 2. Create initial savepoint
curl -X POST https://{EKODB_API_URL}/api/transactions/tx-001/savepoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{"name": "start"}'
# 3. Debit source account
curl -X PUT https://{EKODB_API_URL}/api/update/accounts/ACC001 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{"balance": 900}'
# 4. Create savepoint after debit
curl -X POST https://{EKODB_API_URL}/api/transactions/tx-001/savepoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{"name": "after_debit"}'
# 5. Credit destination account
curl -X PUT https://{EKODB_API_URL}/api/update/accounts/ACC002 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{"balance": 1100}'
# 6. If credit fails, rollback to after_debit
# curl -X POST https://{EKODB_API_URL}/api/transactions/tx-001/savepoints/after_debit/rollback \
# -H "Authorization: Bearer {YOUR_API_TOKEN}"
# Then retry credit operation...
# 7. Commit transaction
curl -X POST https://{EKODB_API_URL}/api/transactions/tx-001/commit \
-H "Authorization: Bearer {YOUR_API_TOKEN}"
Best Practices
Choose Appropriate Isolation Level
| Use Case | Recommended Level | Why |
|---|---|---|
| Analytics/Reporting | ReadUncommitted | Performance over consistency |
| General CRUD | ReadCommitted | Good balance |
| Financial Calculations | RepeatableRead | Consistent reads |
| Banking/Critical | Serializable | Maximum safety |
Use Savepoints for Multi-Stage Operations
Savepoints allow partial rollback without aborting the entire transaction:
# Create savepoint before risky operation
POST /api/transactions/{id}/savepoints
{"name": "before_risky_op"}
# Perform risky operation
PUT /api/update/...
# If operation fails, rollback to savepoint
POST /api/transactions/{id}/savepoints/before_risky_op/rollback
# Retry or continue with alternative approach
Set Appropriate Timeouts
// Short transaction (1 minute)
{"timeout_seconds": 60}
// Long-running workflow (30 minutes)
{"timeout_seconds": 1800}
// Critical operation (5 minutes, default)
{"timeout_seconds": 300}
Handle Errors Gracefully
Always implement proper error handling with rollback:
# Begin transaction
curl -X POST .../api/transactions ...
# -> {"transaction_id": "tx-001"}
# Try operations
if operation_fails; then
# Rollback on error
curl -X POST .../api/transactions/tx-001/rollback ...
else
# Commit on success
curl -X POST .../api/transactions/tx-001/commit ...
fi
Monitor Active Transactions
Track and debug active transactions:
# List all active transactions
GET /api/transactions
# Check specific transaction status
GET /api/transactions/{id}
# Useful for:
# - Debugging stuck transactions
# - Monitoring long-running operations
# - Identifying transaction bottlenecks
Use Cases
Financial Transfers
Multi-account updates with atomicity guarantees:
# Begin transaction
POST /api/transactions
{"isolation_level": "Serializable"}
# Debit source
PUT /api/update/accounts/{from_id}
{"$decrement": {"balance": 100}}
# Credit destination
PUT /api/update/accounts/{to_id}
{"$increment": {"balance": 100}}
# Commit both or rollback both
POST /api/transactions/{id}/commit
E-Commerce Orders
Order creation with inventory reservation:
# Begin transaction
POST /api/transactions
{"isolation_level": "RepeatableRead"}
# Create savepoint before inventory check
POST /api/transactions/{id}/savepoints
{"name": "before_inventory"}
# Reserve inventory
PUT /api/update/inventory/{product_id}
{"$decrement": {"stock": 1}}
# If insufficient stock, rollback to savepoint
# Otherwise create order
POST /api/insert/orders
{...}
# Commit transaction
POST /api/transactions/{id}/commit
Batch Processing
Process multiple records with error recovery:
# Begin transaction
POST /api/transactions
# Process records in batches
for batch in batches:
# Create savepoint before batch
POST /api/transactions/{id}/savepoints
{"name": "batch_{i}"}
# Process batch
POST /api/batch/insert/...
# If batch fails, rollback and continue
if error:
POST /api/transactions/{id}/savepoints/batch_{i}/rollback
continue
# Commit all successful batches
POST /api/transactions/{id}/commit
Related Documentation
- Transactions Architecture Reference - Detailed architecture, isolation levels, and best practices
- Functions Architecture - Function-based transactions (REST API)
- Functions via Client Libraries - Function-based transactions with client SDKs
- Basic Operations - Standard CRUD operations
- Batch Operations - Bulk operations within transactions
- White Paper - ACID compliance and architecture
Example Code
Direct HTTP/REST API Examples
Raw HTTP examples demonstrating the REST API directly:
- JavaScript:
transactions.js - Python:
transactions.py - Go:
transactions.go - Rust:
transactions.rs
Client Library Examples
Production-ready examples using official client libraries:
- Rust:
client_transactions.rs - Python:
client_transactions.py - TypeScript:
client_transactions.ts - Go:
client_transactions.go - Kotlin:
ClientTransactions.kt - JavaScript:
client_transactions.js