Skip to main content
A file submitted with @ is compile-and-run: nothing persists. A stored procedure is the persistent form — the same program, named, stored in the target database itself, and runnable from any host with EXEC name(...). Procedures are how scheduled and repeated work ships: compile once, run forever.

Writing a procedure

A procedure file is the CREATE statement itself:
flag_big_orders.sumatra
The form differs from an anonymous block in three small ways:
  • The header is CREATE OR REPLACE PROCEDURE name(arg TYPE, ...) IS. Write the parentheses only when there is at least one argument — a zero-argument procedure has no () in its header.
  • Declarations come bare between IS and BEGIN — a procedure has no DECLARE keyword.
  • It closes with plain END; (not END name;).
Arguments are positional, read-only inputs, exactly like PARAM declarations: reference them inside SQL as PARAM('cutoff'), casting non-text values at the point of use. There are no OUT arguments, no defaults, and no named-argument calls. A PARAM section inside a procedure is not allowed — the header replaces it. RETURN; anywhere in the body ends the run cleanly (exit 0); work committed before the RETURN stays committed.

Storing it

Submit the file like any other:
Because the file’s program is a CREATE, submitting it stores instead of running: the shell compiles it against the live catalog, builds it, saves the source in the database, and caches the binary on this host. Nothing executes, and a CREATE submission takes no arguments — argument values belong to EXEC. A compile error stores nothing. There is no “invalid procedure” state to discover at 3 a.m.: if it is stored, it compiled.

Running it

EXEC rules:
  • Parentheses always — EXEC nightly() is the zero-argument call.
  • Arguments are positional literals: bare tokens (42, 3.14, 2026-01-01, TRUE) or single-quoted text ('North America'). A text value containing a quote cannot be passed in this release.
  • No trailing semicolon — EXEC is one shell statement.
From a script or cron, use the one-shot form; the exit code is the run’s outcome (0 / 2 / 1):

Where things live

Because the source lives in the database, a procedure stored from your laptop runs from the production cron host with nothing copied around — the first EXEC there compiles it locally and caches the binary.

When recompiles happen

A normal EXEC runs the cached binary with zero compilation. Recompiles happen only for four reasons, and each is announced:
The last one deserves a note: every compiled program bakes in a fingerprint of the table shapes it was compiled against, and re-checks it at run start. If the schema drifted since compile, the binary refuses to run on stale assumptions; the shell then recompiles the stored source against the current schema and reruns — once. If the fresh compile refuses again, the schema is changing underfoot and the run stops loudly.

Managing procedures

DROP PROCEDURE removes the database row and this host’s cache entries. Dropping a name that does not exist is an error, never a silent no-op. To change a procedure, just submit the edited CREATE OR REPLACE file again — replace is last-write-wins. A few operational notes:
  • Procedures do not call procedures. EXEC is a shell statement, not a language statement — composition is sequencing several EXEC lines in your script.
  • Duplicate runs are refused. Two concurrent runs of the same procedure with the same argument values are refused via an engine-side lock marker, so a cron overlap cannot double-apply.
  • The cache key is the database name. If two different Firebolt accounts have same-named databases, they share a host cache directory — use distinct database names (or hosts) to keep them apart.