Query results
Addressable artifacts, and the 7-day clock on them.
A query result in Beetl is not screen state. It is an artifact with an identity, a URL, a storage location, and an expiry date. Understanding all four saves you from the one mistake everybody makes with them.
What a result actually is
When you run a query, the server reserves a result id before dispatching anything. A runner
executes the SQL and writes the output as an Arrow IPC file to your object store, under
query-results/{tenant_id}/{result_id}.arrow. The metadata, including row counts, execution time,
the SQL, and a lineage profile, goes to Postgres.
The browser never touches Arrow. It reads JSON envelopes from the API and renders the table and the chart itself.
The result is addressable:
/web/query-results/{result_id}with sibling routes for the pieces built on top of it:
/web/query-results/{result_id}/chart-options
/web/query-results/{result_id}/drill
/web/query-results/{result_id}/csvRows page through the same endpoint with offset and limit. The table view fetches 100 rows at
a time as you scroll, up to 50,000.
The seven origins
Every result records where it came from. QueryResultOrigin has seven variants, and they all
produce the same kind of artifact:
| Origin | Produced by |
|---|---|
| Ad-hoc | A query you ran in the Query editor. |
| Pipeline preview | Previewing a single SQL stage in the pipeline builder. |
| Chat | The assistant calling execute_query during a conversation. |
| MCP | An external client, such as Claude or Cursor, calling execute_query over MCP. |
| Drill-down | Clicking through from a cell to the rows behind a value. |
| API | A programmatic caller. |
| Automation | A scheduled automation run, where the result becomes the evidence behind its report. |
This matters more than it looks. A number the assistant quotes in chat, a number in an automation report, and a number you got by hand are all backed by the same inspectable artifact. You can open any of them, page the rows, and check.
Ownership and scope
Results are creator-owned and tenant-scoped. You see your own; nobody else in the tenant sees them unless they run the query themselves.
There is no sharing model and no shareable link. Sending a colleague a result URL does not give them access to it. If a result needs to reach someone else, export the CSV or put the query behind a pipeline that writes a dataset a dashboard can read.
Retention
Results expire after 7 days, silently
Default retention is seven days from creation. There is no pin, no save-as-report, no favourite, and no warning before an artifact goes. Opening an expired result shows an explicit "Result expired" state rather than an error, which is the first many people hear about it. If a number has to survive a week, it needs a pipeline behind it or a CSV in your hands.
The Recent results dropdown in the Query page header holds your ten most recent ad-hoc results with their SQL, row counts and creation time. It is a convenience, not storage. Those entries die on the same clock as everything else.
Chart specifications are not persisted at all. Rebuilding the same chart on a result means picking the type and axes again, and the chart disappears with the result. Saved, shareable visuals live in Dashboards instead.
The consequence for automations
An automation report persists. Its evidence does not.
Each automation run writes a Markdown report and links every query it executed to the durable result behind it. The report is durable. The query results it points at expire on the ordinary seven-day clock. An automation report older than a week is therefore a set of conclusions whose evidence links have gone dead.
That is a known and documented consequence, not a bug you are the first to hit. Until retention policy changes, treat an old report as a claim to re-verify rather than a record to cite. See Automations.
What does not expire
Datasets. A pipeline destination writes a Delta table that stays until you delete it, with version history behind it. That is the correct home for anything you intend to look at repeatedly, and the right answer to "can we keep this result" is almost always "make it a pipeline".
One footnote for completeness: results fetched over Arrow Flight SQL, which is how embedded Superset dashboards read tenant data, are transient rather than durable. They are swept every five minutes with a fifteen-minute retention, and they never get a result id at all.