Records

Batch operations

Create up to 1,000 records in one all-or-nothing SQLite transaction.

Request

curl -X POST "$TRESTLE_URL/api/v1/collections/issues/records/batch" \
  -H "Authorization: Bearer $TRESTLE_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"records":[
    {"values":{"title":"Import customer records","priority":3}},
    {"values":{"title":"Verify webhook signature","priority":2}}
  ]}'

If any item fails validation or a physical constraint, none are committed. Error paths include the failing index, such as records[1].values.title.

Why 1,000?

The original 100-record ceiling was an intentionally conservative checkpoint default, not a SQLite limit. A 1,000-record transaction is large enough for practical ingestion while bounding memory, audit work, rollback cost and the size of indexed validation errors. The request body ceiling is 8 MiB.

Importing larger datasets

for (const records of chunks(sourceRows, 1000)) {
  await trestle.batchCreate("issues", records);
}

Commit chunks sequentially and retain the source offset after each successful response. If strict whole-file atomicity is essential, stage the import outside the public request path and promote it only after validation.

Atomicity

Batch writes commit in one transaction on both providers: a rejected record rolls the whole batch back with no partial state, up to the 1,000-record bound. The provider-parameterized suite verifies identical commit and rollback behavior on SQLite and PostgreSQL.