Skip to main content
Use the structured query API for most reads and writes. It provides explicit fields, filters, grouping, sorting, pagination, and JSON-path behavior without assembling SQL strings.

Read rows

getDatabaseData(), getDatabaseDataRow(), countDatabase(), and walkDatabaseData() accept a Database, live View, or Materialized View by logical name. Structured joins can combine those readable relation types, with access checked for each source. If a legacy instance contains the same logical name in more than one relation type, the read fails until the ambiguity is resolved.
Prefer a narrow field projection. getDatabaseData() accepts an explicit non-negative take (maximum 100,000) or take: null for a bounded 2,000-row page. Omitting take (or the query) also defaults to 2,000 rows and logs one warning per execution; specify take deliberately. Use walkDatabaseData() with fullScan: true for a complete scan. Do not page through a large table with skip += 200. For one matching record, use getDatabaseDataRow(name, query). It returns the row or null in one database operation, without a collection wrapper. Omit take, skip and count; add sort when several rows match and the chosen row matters. tx.getDatabaseDataRow() supports row locks within a transaction.

Process large results

Use walkDatabaseData() for a Job that processes many rows. Specify either a non-negative take or fullScan: true; a missing take does not silently scan the whole table. The default batchSize is 10,000 (accepted range: 1,000–10,000). Each non-final callback receives exactly that many rows if available, and callbacks are awaited sequentially.
Process each batch before the next one arrives; do not accumulate every row in an array. Use fullScan: true only when processing until the end is intentional. A single wide row can still be expensive: select only the columns needed. Jobs remain subject to their timeout and resource limits. The walker selects a pagination strategy appropriate to the query. There is usually no need to select a strategy manually. For a count without loading rows, use one call:
Database calls share a limit of 8 active operations and 64 waiting admissions per execution, including Jobs. Small operations are paced by 300 ms after 1,000 calls and 500 ms after 2,000 calls; these counters cover the entire execution rather than a minute or hour. Insert, upsert and delete batches with at least 100 supplied rows do not consume this small-operation budget. Read batches qualify only when at least 100 rows are actually returned; a large take or total count does not exempt a small read. Small reads are paced before returning their result to your script. Batches do not reset the small-operation counter. A walker costs one opening call regardless of its internal batches. Prefer bulk writes and the walker over repeated single-row calls. Dedicated getSecret() / getSecrets(), Storage, Files, Agent and orchestration calls are outside this database throttle; all getInstanceData() calls are included.

Export readable relations

Use api.exportDatabase(name, options) for Databases, live Views, and Materialized Views, including supported structured joins. The former View-only read helper remains a deprecated compatibility alias. Replace api.exportDatabaseView() with api.exportDatabase(); the View-specific export helper is no longer part of the current contract. CSV is the default; select format: 'tsv', 'ndjson', or 'xlsx' when the consumer needs it. By default low-code waits for the final Storage entry. Set async: true to receive a jobId and follow the export as a Database operation instead of holding the current execution open.

Import Storage data

Use api.importDatabase(name, options) to preview a Storage-backed CSV, TSV, NDJSON, or XLSX file. Supply storageEntryId, format, mode (insert or upsert), and onError (abort or skipRow). The call returns an import ID and operation job ID; preview validates rows and proposes a source-column mapping without writing to the target. Read the Database operation status and validation report before committing. System messages and emails are suppressed by default; set skipNotification: false to opt in, subject to notification preferences. See Import from Storage for the browser upload lifecycle and exported-value conventions. When the mapping needs correction, call api.updateDatabaseImportMapping(importId, mapping) and wait for revalidation. Then call api.commitDatabaseImport(importId) to start the write. Commit rejects unresolved decisions and checks that the Storage source and target definitions still match the preview. autoCommit skips manual approval only after the same full validation; ambiguous mappings still require review. See the generated low-code API reference for the exact method signatures.

Mutate rows

Use the dedicated insert, upsert, update, and delete methods. Bulk update and delete accept the canonical structured filter tree.

Partial updates are the default

api.updateDatabaseData() updates one row identified by its primary-key object. Put only the properties that change in newObject; omitted and undefined properties are preserved. A present null deliberately clears a nullable property. api.upsertDatabaseData() follows the same PATCH rule on a primary-key conflict. It creates a missing row from the supplied data, but when the row already exists it changes only properties present in that input object. Do not fetch a full row merely to change one property.
The third argument controls the response for both insertDatabaseData() and upsertDatabaseData(): api.deleteDatabaseData() accepts objects containing the Table’s primary-key fields; server-owned row metadata is not required. Use deleteDatabaseDataRequest() when a structured filter identifies the rows without loading their keys first. For a multi-row PATCH selected by a structured filter, use api.updateDatabaseDataRequest():

Transactions

Use api.transactionDatabase() for check-then-write workflows that must commit together.
Await transaction calls sequentially. Keep sleeps and remote HTTP/SFTP side effects outside the callback because a transaction reserves a connection and may hold row locks.

Raw SQL

api.queryDatabase() is for parameterized SELECT or WITH reads when the structured builder cannot express the query. Use the mutation helpers for writes.
Last modified on October 14, 2026