Transactions
Pulsabase SDKs support database transactions, allowing you to execute multiple queries as a single, atomic operation.
If any query within the transaction fails, the entire transaction is rolled back, ensuring your database remains in a consistent state. If all queries succeed, the transaction is committed.
How it works
Section titled “How it works”Transactions in Pulsabase are built using the pb.transaction() method. You construct your individual queries using the standard query builder methods prefixed with build (e.g., buildInsert, buildUpdate, buildDelete), extract the raw JSON requests using .toPayload(), and pass them as an array to the transaction executor.
import pb from 'pulsabase';
try { // Execute an atomic transaction const results = await pb.transaction([ pb.from('accounts').where('id', '=', 1).buildUpdate({ balance: 50 }).toPayload(), pb.from('accounts').where('id', '=', 2).buildUpdate({ balance: 150 }).toPayload(), pb.from('audit_logs').buildInsert({ action: 'transfer', amount: 50 }).toPayload() ]);
console.log('Transaction succeeded!', results);
} catch (error) { console.error('Transaction failed and was rolled back:', error);}import 'package:pulsabase/pulsabase.dart';
try { // Execute an atomic transaction final results = await pb.transaction([ pb.from('accounts').where('id', 1).buildUpdate({'balance': 50}).toPayload(), pb.from('accounts').where('id', 2).buildUpdate({'balance': 150}).toPayload(), pb.from('audit_logs').buildInsert({'action': 'transfer', 'amount': 50}).toPayload(), ]);
print('Transaction succeeded! $results');
} catch (e) { print('Transaction failed and was rolled back: $e');}curl -X POST https://api.yourproject.pulsabase.com/query \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "action": "transaction", "requests": [ { "action": "update", "table": "accounts", "query": { "id": 1 }, "payload": { "balance": 50 } }, { "action": "update", "table": "accounts", "query": { "id": 2 }, "payload": { "balance": 150 } }, { "action": "insert", "table": "audit_logs", "payload": { "action": "transfer", "amount": 50 } } ] }'Supported Operations
Section titled “Supported Operations”Transactions in Pulsabase support a wide range of atomic operations. The transaction executor in the Core engine uses the exact same execution paths as standalone queries.
Mutations
Section titled “Mutations”buildInsert(payload).toPayload(): Inserts one or more records. Returns the inserted records with generated fields (likeidandcreated_at).buildUpdate(payload).toPayload(): Updates records matching a.where()condition. Returns the updated records.buildDelete().toPayload(): Deletes records matching a.where()condition. Returns the deleted records.buildUpsert(payload, onConflict).toPayload(): Inserts new records or updates existing ones automatically if a conflict occurs on specific columns (PostgreSQLON CONFLICT DO UPDATE).buildBulkUpdate(instructions).toPayload(): Executes multiple different updates in a single core operation using an instruction array.buildBulkDelete(instructions).toPayload(): Executes multiple different deletes using varied filters in a single core operation.
While transactions are primarily used for atomic writes, you can include read queries to ensure they are executed against the exact same data snapshot:
buildFind().toPayload(): Selects multiple rows inside the transaction snapshot.buildFindOne().toPayload(): Selects a single row inside the transaction snapshot.
Note: Complex nested relation insertion (
insertWith) is currently not supported inside transaction arrays. Real-time publication events are emitted only after the database transaction is successfully committed.