Schema for Transactions.
Transactions don't change the schema TOML. Whatever fields you declared on the wrapped schemas (PKs, indexes, FKs, CHECKs) are enforced inside the tx the same way they're enforced in a plain row write. Read-committed isolation, single-writer, flat (no savepoints or nested transactions). Writes are buffered at BEGIN and flushed atomically at COMMIT.
Engine surface: POST /v1/tenants/:t/tx/begin · GET /v1/tenants/:t/tx/:tx_id · POST /v1/tenants/:t/tx/:tx_id/commit · POST /v1/tenants/:t/tx/:tx_id/rollback.
Required schema fields.
Without these, this query surface doesn't function at all.
| field | effect |
|---|---|
| (none for the tx machinery itself) | Transactions wrap SQL / row writes. Schemas of the wrapped writes need their usual fields, but /tx/begin doesn't read any schema. |
Optional fields — what each one unlocks.
Add only the fields whose effect you need. Each one buys a specific capability — speed up a predicate, guard a write, or unlock a new query shape.
| field | type | default | effect |
|---|---|---|---|
| [[foreign_keys]] / [[check_constraints]] on the wrapped schema | object | — | Enforced INSIDE the transaction - a violation aborts the whole tx, not just the offending write. |
What you can call.
- POST /tx/begin - open a new transaction (returns tx_id)
- GET /tx/:tx_id - read tx status (running | committed | aborted)
- POST /tx/:tx_id/commit - flush all buffered writes atomically
- POST /tx/:tx_id/rollback - discard the buffered writes
- Row writes with the tx_id attached are buffered until commit
- Multi-row writes commit as one atomic WAL frame
Abbreviation legend.
| token | meaning |
|---|---|
| tx_id | ULID returned from /tx/begin. Attach to subsequent row writes to bind them to the tx |
| buffer-at-BEGIN | Writes inside a tx are buffered in memory until commit |
| flush-at-COMMIT | All buffered writes flush to the WAL atomically on commit. Either all land or none do |
| read-committed | Reads see the latest committed state; reads inside the same tx don't see the tx's own buffered writes |
Worked example.
Schema TOML — copy + register via POST /v1/tenants/:t/schemas with Content-Type: text/plain.
# Tx wraps your existing SQL / row writes — no extra TOML fields.
# Constraints declared on the wrapped schema are enforced inside the tx:
namespace = "shop"
table = "products"
primary_key = ["id"]
[[columns]]
name = "id"
ty = "str"
required = true
[[columns]]
name = "price_cents"
ty = "i64"
# This CHECK applies to writes via SQL, /rows, AND inside transactions:
[[check_constraints]]
name = "price_positive"
expression = "price_cents > 0" Queries it enables.
# Begin a transaction
RESP=$(curl -X POST $BASE/v1/tenants/$T/tx/begin \
-H "Authorization: Bearer $BEARER" -H "Content-Type: application/json" -d '{}')
TX_ID=$(echo "$RESP" | jq -r .tx_id)
# Inspect status
curl $BASE/v1/tenants/$T/tx/$TX_ID -H "Authorization: Bearer $BEARER"
# Do work - attach the tx_id to row writes via the X-OC-Tx-Id header.
# Writes are buffered until commit; nothing is durable yet.
# Commit - all buffered writes flush to the WAL atomically
curl -X POST $BASE/v1/tenants/$T/tx/$TX_ID/commit -H "Authorization: Bearer $BEARER" -d '{}'
# Or rollback - discard the buffered writes
curl -X POST $BASE/v1/tenants/$T/tx/$TX_ID/rollback -H "Authorization: Bearer $BEARER" -d '{}'