Elizon Docs
Data Tables

Introduction

A Data Table is a typed table your workflows read and write — the register that makes a run remember.

A Data Table is a small typed table that belongs to a project. A workflow writes rows into it with a Data Table node, and people read and correct those rows on the Studio → Data Tables page.

It exists for the thing a single run cannot do: remember. Extract a contract today, and a schedule three weeks from now can still find its deadline, because the deadline is a row rather than a value inside a finished run.

A workflow is not the only thing that can use a table:

  • an Agent can read it, and add or change rows — reads and each kind of write are switched on separately, per table, and an Agent can never delete;
  • an Agent's skill scripts can read a whole table as a file, when that is switched on for the table;
  • a workflow's Code node can read matching rows as a file.

A Package can ship a table and wire all of these to it; the authoring reference is Data Tables in the portable-definitions spec.

What a table is made of

PartWhat it is
NameUnique inside the project, compared without regard to case.
ColumnsOrdered, each with a name and one of four types. The order you declare is the column order.
RowsOne value per column, plus three system fields Elizon maintains.

The four column types are boolean, date, number and string. There are no joins, formulas or relations, and a column's type cannot be changed once rows exist — add a new column instead.

Every row also carries three system fields you never declare and cannot use as a column name:

FieldMeaning
idThe row's identity (a UUID).
createdAtWhen the row was first written.
updatedAtWhen it was last changed.

You can sort and filter by them like any other field.

Values and empties

A cell holds a string, a number, a boolean, a date — or null, which is the single representation of empty for every type. An object or an array is not a value: a write that puts one in a cell is refused rather than stored as JSON, because no filter could compare it afterwards.

Values are checked on write, against the column's own type, and a refusal names the column, the type it expected and the value it got:

Column "Deadline" expects a date; received the string "next tuesday".
Accepted: an ISO 8601 date (2026-10-02) or date-time (2026-10-02T09:00:00Z), or null.
TypeAccepted on write
booleantrue, false, "true", "false", or null
dateAn ISO 8601 date (2026-10-02) or date-time (2026-10-02T09:00:00Z)
numberA finite number or a numeric string
stringA string, a finite number, a boolean, or null/"" for empty

A date is stored as a timestamp, so a value written as 2026-10-02 reads back as 2026-10-02T00:00:00.000Z.

Where a table lives

A Data Table belongs to one project — not to the organization, and not to a workflow. That is also the whole of its access control: a run in another project, or in another organization, cannot read or write it, by its name or by its id.

A brand-new organization has no projects at all, so create a project before you create a table.

Who may do what

Four permissions, independently grantable to a custom role:

PermissionAllowsOwnerAdminEditorNormal
data_tables.viewSee the tables, their columns and their rows✔✔✔✔
data_tables.createCreate a table✔✔✔—
data_tables.editRename a table; add, rename and remove columns; write rows✔✔✔—
data_tables.deleteDrop a table, and everything in it✔✔——

A workflow run has no role. What a Data Table node may do is decided by the node's own configuration — which is why dropping a table from a workflow needs the node's explicit Allow deleting tables flag.

Limits

Every limit is a platform setting your operator can raise or lower; these are the defaults.

LimitDefault
Tables per project50
Columns per table50
Rows per table100,000
Bytes per row64 KB
Rows returned by one read1,000
Statement timeout5 s
Conditions in one filter50
Sort keys in one read8
Rows in one write20,000
Row source file size50 MB
Bulk statement timeout60 s

KB and MB are binary multiples: 1 KB = 1,024 bytes, and 1 MB = 1,024 KB (1,048,576 bytes).

A write that would cross a limit is refused with the limit named, and a read that asks for more rows than the ceiling allows is clamped to it rather than refused — so "return all rows" means "up to the ceiling", never "unbounded". To read past the ceiling, page with a cursor, or read every matching row as a file.

Rows in one write bounds a bulk upsert and an insert, and Row source file size bounds the file a bulk write reads its rows from and the file a read as a file writes. The statement timeout bounds any query whose filters an author controls; the bulk statement timeout replaces it for a bulk upsert, an Optimize Bulk insert, a read as a file and a Studio import.

When a statement times out

Every Data Tables operation runs as one database transaction. When a statement in it runs past its timeout, the database cancels it and the whole transaction is rolled back: nothing the operation would have written is kept, and a read returns the error rather than partial rows.

A timeout is not one of the refusals that names its cause. Studio shows a generic internal error, a Data Table node fails with the message The Data Table operation could not be completed (internal error)., and an Agent's Data Table tool call fails with a generic internal error. That the timeout fired is recorded only in the server log, where your operator can see it.

Time spent waiting for a lock counts too: an upsert, a bulk upsert and a Studio import wait for locks on the table or the key, so on a busy table — other writes to the same table or the same key — even a small operation can run out of time.

To stay under the timeout, narrow the filters so fewer rows are scanned, page through a large read with a cursor or read it as a file, or split a large write into smaller ones. Smaller writes are separate transactions and no longer roll back together, so make each one safe to repeat — an upsert by key, for example — before re-running after a failure. If the operations are as small as they can be, your operator can raise DATA_TABLES_STATEMENT_TIMEOUT_MS or, for the bulk operations, DATA_TABLES_BULK_STATEMENT_TIMEOUT_MS.

Next