Column types
Each column has a type that drives its cell editor and how queries match it:
- text — short single-line string (up to 4 KB).
- large text — free-form prose or blobs, edited in a side panel (up to 64 KB).
- number — numeric; the currency, percent, and rating variants are numbers with formatted editors.
- boolean — a checkbox cell.
- date, datetime, time — temporal values.
- select / multi-select — a dropdown from a fixed
optionslist (up to 200 choices). Multi-select stores an array. - array — a free-form list of strings, edited as a tags input; your code reads an array.
- url, email, phone — string variants with validation-friendly editors.
- JSON — a structured value edited in a JSON editor (up to 64 KB).
- auto increment — a system-managed unique record id. The cell is auto-filled with a fresh unique id when the row is inserted and is immutable thereafter (writes are ignored), giving you a stable, human-visible handle to a record. (It's an auto-generated unique id, not a sequential counter.)
The auto-increment id and the row _id
Two distinct identifiers exist. Every row always has an internal _id — the handle the SDK, workflow tasks, and agent tools use to address a row for update / delete; it's read-only and assigned automatically. An auto increment column is optional and owner-facing: add one when you want a stable id you can see and match on in your own queries. Row actions can be told which column is the primary id; when none is set they fall back to the row _id.
Editing rows
Edit cells inline in the grid; edits are debounced and auto-saved (a "Saving…/Saved" indicator reflects the request). Large-text and JSON cells open a dedicated side editor — make changes and click Save. Add rows with + Row; reorder columns by dragging the grip handle on a column header.
Soft-delete and restore
Deleting a row — from the grid, the SDK, a workflow, or an agent — is a soft delete. The row drops out of every read immediately but isn't erased:
- Open Recently deleted on the sheet to see deleted rows (newest first), each with a preview and a Restore button that puts the row back.
- Deleted rows are kept for 90 days, then permanently purged — the same recovery window FlowFn applies to other deleted content.
- Two actions remove rows permanently with no recovery: a CSV import in Replace mode and an AI full-replace of the sheet. Deleting the sheet or the whole database soft-deletes its rows along with the parent, purged on the parent's 90-day schedule.
The query DSL
Reads against a sheet take a where filter, evaluated on the server so you only download the rows you need. The same DSL is used by flowfn.data.query / findRow / findRows in playgrounds, by ctx.sheets.query in server code, by the Data Sheet workflow task's match filter, and by the agent sheet tools.
{
where: { price: { gte: 10, lt: 100 }, name: { contains: 'pro' } },
or: [{ featured: true }, { rating: { gte: 4 } }],
sort: { price: 'asc' }, limit: 25, offset: 0,
}
Operators: a bare value means equals; or use an operator object — eq, ne, gt / gte / lt / lte (number & date columns), in / nin (arrays), contains / startsWith (text columns), and exists (true/false). Multiple keys in where are AND-ed; use or for alternatives. Values are matched against the column's type, and limit is capped (default 50).
Limits
- Databases per app — plan-tuned (
max_databases_per_app;-1= unlimited). - Sheets per database — plan-tuned (
max_data_sheets_per_database; default ceiling 20). - Rows per sheet — plan-tuned (
max_data_sheet_rows). - Up to 50 columns per sheet; up to 200 options on a select / multi-select column.
- Cell sizes: ~4 KB for text, ~64 KB for large-text and JSON cells.
- Up to 10 owner-defined row actions per sheet (see Public sheet writes).