Deploy and trigger
Deploying a pipeline, running it by hand, and running it when a source updates.
A pipeline writes its destination only after you deploy it. For the Working and Deployed versions, see Pipelines.
Save, Deploy and Run
| Action | Where | What it does |
|---|---|---|
| Save | Editor header, Working view | Stores your draft as the next Working version. Writes nothing. |
| Deploy | Editor header, Working view | Checks the saved Working version, makes it the Deployed version and starts a first run, which writes the destination. |
| Run | Editor header in the Deployed view, or Run pipeline on the pipeline's node on Home | Runs the Deployed version again and writes the destination. |
Deploy is unavailable while you have unsaved changes. Previewing a stage never writes.
What Deploy checks
Beetl refuses the deploy unless all of these hold for the saved Working version:
- The pipeline has a destination, and it is not a registered or external dataset.
- Every source with Trigger on update can supply every
run.*value the pipeline uses. If one cannot, the error names it, for exampleSource `orders` cannot satisfy run context: missing required values: run.dt. - Every
run.*reference has a value. Preview and Deploy ask for these in a Provide run values dialog, which remembers your entries until you close the editor. - A dry run of all stages with those values succeeds. The dry run writes nothing.
The first run then starts with the run values you entered. If Deploy fails with a general error, the dry run failed: preview the last stage with the same run values to see the full message.
Three cases behave differently:
- If the Working version is identical to the Deployed version, Deploy changes nothing and starts no run. Use Run instead.
- If the pipeline is disabled, Deploy promotes the new version but starts no run.
- The dry run checks that your SQL runs, not that its result fits an existing destination. A changed column list or type fails the first run without writing. See Schema compatibility.
Run a deployed pipeline
Switch the editor header to Deployed and press Run, or choose Run pipeline on the
pipeline's node on Home. If the Deployed version uses run.* values, a dialog asks for them.
Run stays unavailable until these are true, and its tooltip names the one that is missing:
| Condition | Tooltip |
|---|---|
| The pipeline has a destination | Add a destination before running this pipeline |
| The pipeline is enabled | Enable this pipeline before running it |
| A version has been deployed | Deploy this pipeline before running it |
Trigger on update
While a source card's Trigger on update switch is on, every write to that source by a sync, webhook, file processor or another pipeline starts a run. Registered and external datasets never trigger runs.
The run mapping
The run mapping decides which run.* values a triggered run receives. For a partitioned source, the
card lists each partition column as a Source event field, such as
{{ source.partition.values.dt }}, with an Available as name that starts as the column name.
Rename it when your SQL uses a different name, for example day for a dt partition.
A write that touches several partitions starts one run per partition, each with that partition's
values. A write to an unpartitioned source starts one run with no run.* values. When several
sources trigger, each starts runs on its own; Beetl does not wait for the others to catch up.
Chat and MCP clients can also set mapping templates, such as
{"dt": "{{ source.partition.values.invoice_date }}"}.
The WARN badge
A source card shows WARN when Trigger on update is on and the source cannot supply a run.*
value the pipeline uses; hover to see which. Deploy refuses until you rename the Available as
entry, change the template, or turn off Trigger on update for that source.
Runs wait their turn
A pipeline executes one run at a time, and the rest wait as Queued. If a source update arrives while a run with the same run values is still queued, Beetl does not queue another. Different pipelines run in parallel.
Enable and disable
Disable and Enable are on the pipeline's node on Home. A disabled pipeline starts no runs, whether from source updates, Run or a deploy, though you can still edit and deploy it. Updates it missed are not replayed when you enable it again, so run it by hand.
Read the Runs tab
Select the pipeline's node on Home and open Runs. Each row shows start time, status and duration; expand it for the error, the trigger, and the queued, started and finished times. A run moves through Queued, Dispatched and Running to Completed or Failed.
| Trigger | Started by |
|---|---|
| Manual | Run in the editor or on Home |
| Event | An update to a source with Trigger on update |
| System | The first run after a deploy |
Deploy from chat or MCP
In chat, the assistant asks you to confirm before it deploys; save or dismiss unsaved editor changes first. If the pipeline changes before you confirm, the deploy is refused.
Over MCP, deploy_pipeline with a write key deploys at once, and the first run writes the
destination. Pass run values as initial_run_context, for example {"run": {"dt": "2026-10-03"}}.
Treat a write key like a deploy credential; see
The agent trust boundary.
Neither chat nor MCP can rerun a deployed pipeline. run_pipeline only previews the stored Working
version. To rerun, use Run in the app.
Run on a timetable
Pipelines have no schedule of their own. Trigger them from a sync that has one:
Create a sync with a daily schedule and Sync time partitioning, so each sync run writes rows
with that day's dt. See Integrations.
Add the sync's dataset as a source with Trigger on update on. Its run mapping offers dt.
Filter on run.dt, set the destination to Overwrite with the predicate dt = '{{ run.dt }}', and
deploy with a recent date as the first run's value.
SELECT order_id, customer_id, amount, dt
FROM orders
WHERE dt = DATE '{{ run.dt }}'Each sync run now replaces one day of output.
Related
Last updated on