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.