Procedures
A procedure is named, callable logic stored in the catalog next to the data it operates on. In an architecture where frontends query the database directly, procedures are where multi-step business operations live - invoked with call, executed transactionally, governed by policies like any other object.
Creating and calling
The body is a block of statements; calling the procedure returns the result of its last statement. Run the snippets on this page in order:
Parameters
Parameters are declared as a typed record and referenced in the body with a $ prefix. Calls pass arguments positionally:
The body is a full script
Procedure bodies are ReifyDB Scripting, not just single queries: variables with let, conditionals, loops, and any number of reads and writes. See Parameters & Control Flow for the scripting constructs in depth.
Procedures compose - a procedure can call another:
Test procedures
ReifyDB's testing framework runs inside the database. create test procedure declares a helper callable only from test context - fixtures like seeding rows - and create test plus run tests execute assertions against real data:
Each test runs in a transaction that is rolled back, so tests never leak state into your data - the seeded row does not survive the run:
Beyond RQL bodies
RQL is one of several procedure kinds the catalog manages. Procedures can also be backed by built-in native implementations, by functions loaded from FFI libraries, or by WASM modules - all invoked through the same call statement with the same typed parameters. Event-driven logic, by contrast, is not a procedure kind: declare an event and attach handlers, which run automatically on dispatch instead of being called.
Access control
Who may invoke a procedure is governed by a policy with the call operation: create procedure policy on ns::proc { call: { filter { ... } } }. Like all policies, procedure policies apply to non-root identities.
