Guides
GuideLinked Records & Rollups

Linked Records, Lookup & Rollup

Connect tables to each other, show values from connected records, and calculate totals across them — like "each Customer's Orders" and "the sum of those orders".

Three field types work together: a Link connects rows in one table to rows in another; a Lookup shows a field from the connected rows; a Rollup turns those values into one number or text (sum, count, average…).

All of it is calculated by the database itself, straight from the live data — values are always current, and open grids update in real time when connected records change.

Lookup Fields

A Lookup shows a field from the connected records without copying it. Example: on each Customer, show the titles of their linked Orders.

When you create one you pick: which link to follow, which field to show from the other table, and how to show it:

Display choiceWhat you see
Show all valuesComma-separated list — "Alpha, Beta"
First / Last valueJust one value, following the link order
List of valuesThe values as a list
Count / Sum / Average / Min / MaxA quick calculation over the values

Rollup Fields

A Rollup reduces the connected records to a single answer. Example: each Customer's Total = the sum of their Orders' amounts.

CalculationMeaningWith no linked records
Count linked recordsHow many records are connected0
Count non-empty / empty / uniqueCounts over the chosen field's values0
SumAdds the numbers up0
Average / MedianTypical value of the numbersblank
Minimum / MaximumSmallest / largest numberblank
Join valuesComma-separated text of the valuesblank
List of values / unique valuesThe values as a listblank

Empty cells and blank text are ignored by number calculations — a task with no Points doesn't drag the Average down.

Conditions & Chains

Only include records where… — both lookups and rollups can take an optional condition, so only the connected records that match are counted. Example: a Customer's "Outreach Limit" = sum of linked Sending Accounts' Daily Limit, only where Purpose is Outreach. Set it right in the Add Column dialog.

Chains — a lookup or rollup can read a field that is itself computed on the other table. Example: each Company has a rollup of its Cities' population; a Region can then sum its Companies' rollups. Chains resolve fresh from the live data (up to 3 computed hops), and a chain that would loop back on itself is rejected when you try to save it.

Always Up To Date

Lookup and rollup values are calculated by the database from the live data every time they are read — there is no cached copy that can go stale. If someone edits, links, unlinks, or deletes a connected record, every affected value is correct on the very next read, and grids that are already open update in real time, even across tables.

Example: your Customers grid is open showing Acme's Total of $150. A teammate edits one of Acme's orders from $100 to $200 in the Orders table. Acme's Total changes to $250 on your screen without a refresh.

Rules & Behavior

  • Read-only: lookup and rollup cells can't be typed into — their value always comes from the connected records. Writes that include them are accepted and the computed keys are simply ignored, so integrations that read a row and send it back never break.
  • Filterable: view filters work on lookup/rollup values ("Total greater than 100", "Statuses contains blocked") and run in the database for speed. List-style values filter more slowly on large tables.
  • Link order matters: "First value" and joined text follow the order of the chips — drag to reorder links and the values follow.
  • Deleting records: deleting a connected record removes it from every calculation automatically.

In the SDK & Backend Functions

Computed values are included in every row you read — no extra calls:

// Lookup/rollup values arrive with the row, already calculated
const { rows } = await ctx.tables.getRows('Customers', { limit: 50 });
rows[0].data['Total'];        // e.g. 250 — the rollup value
rows[0].data['Order Titles']; // e.g. "Alpha, Beta"

// Writing them back is harmless — computed keys are ignored
await ctx.tables.updateRow('Customers', rowId, rows[0].data);

Filtering by computed fields is supported in view filters (the grid). The filterRows API can't filter by lookup/rollup values — for computed-field conditions in code, use raw SQL via ctx.tables.query in a backend function ("Total" and friends are real queryable columns there).

Linked records themselves are managed with the linked-records API (link, unlink, reorder) — see the backend functions reference.