Database Workflows
A Database Workflow is a reusable automation that runs business logic against the data model - looking up records, saving changes, submitting for approval, calling other functions, looping over collections, and routing based on conditions. Workflows run inside PostgreSQL as PLV8 functions, which means they are best suited for short, transactional work that stays within the platform: saving and submitting records, validating data, coordinating other workflows or server functions. For anything that calls external APIs, uses AI, handles files, or may run for seconds or longer, use a Server Function instead.
Database Workflow or Server Function?
Section titled “Database Workflow or Server Function?”| Use a Database Workflow when | Use a Server Function when |
|---|---|
| Logic only reads/writes platform records | You need to call an external HTTP API or webhook |
| Validation, submission, or approval logic | You need AI generation or embeddings (api.ai.*) |
| Coordinating saves across multiple entities | You need to send email (api.mail.send) |
| Calling other workflows or functions | You need file storage or URL fetch (api.files.*) |
| Logic completes quickly (milliseconds) | The task may run for seconds or longer |
| You want point-and-click Design mode | You need secrets management (api.secrets.*) |
When in doubt: if the work stays entirely within the platform and runs fast, use a Database Workflow. If it touches the outside world or might take time, use a Server Function. The two are designed to work together - a Database Workflow can call a Server Function as a step whenever it needs to hand off work that crosses those boundaries.
The Database Workflows screen
Section titled “The Database Workflows screen”Navigate to Automation - Database Workflows to see all workflows in the current application:
| Column | Description |
|---|---|
| Workflow Name | Human-readable name |
| Definition Type | Design or AI/Code |
| Module Name | Which module the workflow belongs to |
| Created By | The user who created it |
| Modified On | Last modification timestamp |
| Published On | When the workflow was last published |
| Status | A checkmark (✓) if published and current, or a Publish link if there are unpublished changes |
Use + Add to create a new workflow, and the row checkboxes plus Delete to remove workflows in bulk.
Creating a workflow
Section titled “Creating a workflow”Database Workflows can be built two ways, chosen at creation and cannot be changed afterwards:
- Design mode - a visual canvas where you assemble steps point-and-click, connecting them into a flow without writing code.
- AI/Code mode - a PLV8 code editor with AI assistance for when you need full programmatic control.
Clicking + Add opens the Add Database Workflow panel. The first and most important choice is Definition Type:
- AI/Code - creates a PLV8 function you write (or generate with AI) directly as code. Fields: Function Name, Function ID (auto-generated), Function Module, Description.
- Design - creates a visual workflow built from steps on a canvas. Fields: Workflow Name, Workflow ID (auto-generated), Workflow Module, Input Structure, Output Structure, Description.
Input Structure and Output Structure are optional. When set, they define the typed shape of data passed into the workflow and returned from it - using a Structure defined in Data Model. Setting an Output Structure also unlocks the output mappings option on each step’s End configuration, so step results can be mapped to the workflow’s return value.
The definition type cannot be changed after the workflow is saved.
Workflow detail view
Section titled “Workflow detail view”Click a workflow to open its detail view. Publish sits at the top left. Top right actions: Security Rules, Clone. Run Workflow (next to the tab row) lets you test the workflow directly without leaving the detail view.
The Workflow Details card on the Details tab shows the workflow’s configuration. Click Edit to change any of these settings, including three execution options:
| Setting | Description |
|---|---|
| Log Execution | Whether each execution is recorded in the execution log |
| Run Async | Whether the workflow runs asynchronously - does not block the caller while it runs |
| Run Under Transaction | Whether the workflow runs within a single database transaction |
The tabs below depend on the definition type:
- Design workflows: Details, Diagram
- AI/Code workflows: Details, AI/Code, Logs
Design mode
Section titled “Design mode”The Diagram tab is the visual canvas. A breadcrumb at the top shows your current location in the workflow - Main at the root level, and Main > [step name] when you drill into a Foreach step’s inner canvas.
Zoom controls sit at the bottom left: +, -, and a fit-to-screen button.
The canvas
Section titled “The canvas”Every Design workflow has two fixed terminal nodes:
- Start (▶) - where execution enters the workflow
- End (■) - where execution exits
Steps appear between them as icon nodes, connected by dashed arrows. The canvas is empty when a workflow is first created, showing a “No Steps Yet” message and a central + Add Step button.
Adding and connecting steps
Section titled “Adding and connecting steps”Click + Add Step on an empty canvas to open the Select Workflow Step picker - a grid of the nine available step types. Select one to begin configuring it.
Once a workflow has steps, new steps can be added inline from the Next Step panel at the end of any step’s configuration (see Next Step configuration below).
Steps connect to each other via their Next Step setting. A step can point to any other step or to End. Condition and Review steps have two outgoing paths each; all other steps have one.
Step interactions on the canvas
Section titled “Step interactions on the canvas”Hovering a step node reveals action icons above it:
- Unlink left - disconnects this step from its predecessor (the step that currently points to it)
- Delete (red trash) - removes the step entirely
- Unlink right - disconnects this step from its successor
Foreach steps additionally show a drill-into icon that opens the step’s inner canvas.
Clicking a step node (not a hover icon) opens its configuration panel to edit it.
Step configuration
Section titled “Step configuration”Every step is configured through a short panel flow. Most steps have three screens: Step Settings, Step Input, and Next Step. Some steps (Condition, Expression) embed their logic in the Settings screen and skip a separate Input screen.
All steps share two common fields at the top of their Settings screen:
| Field | Description |
|---|---|
| Step Name | Human-readable label shown on the canvas node |
| Step ID | Auto-generated from the name; used as the step’s identifier in the workflow context |
Lookup record
Section titled “Lookup record”Finds a single record matching a filter and makes its fields available to subsequent steps. Returns the first matching record, or nothing if no match is found. This is distinct from Foreach, which works with a full collection.
Step Settings:
| Field | Description |
|---|---|
| Record Type | Entity, Component, or View |
| Entity / Component / View | The specific target to look up |
Step Input (Mappings):
Each mapping row filters the lookup: a Target field on the record, a Mapping Type (Maps To a context value, or Has Value for a fixed constant), and a Source from the workflow context. Use + Add new mapping to add filter conditions.
Output (available to subsequent steps): the retrieved record and all its fields.
Save record
Section titled “Save record”Writes field values to a record (creating or updating it) and makes the record identifiers available to subsequent steps.
Step Settings:
| Field | Description |
|---|---|
| Record Type | Entity or Component only (Views are read-only) |
| Entity / Component | The specific target to save to |
Step Input (Mappings):
Each mapping row sets a field on the target record from the workflow context. Same mapping row structure as Lookup record.
Output (available to subsequent steps): record identifiers - System ID (thing_id) and System Version (version_id) for versioned entities/components; Entity ID for system entities.
Submit
Section titled “Submit”Advances a record from Draft to Submitted in the record lifecycle. Only needs to know which record to act on - it does not set any field values.
Step Settings:
| Field | Description |
|---|---|
| Entity | The entity to submit a record of (no Component or View) |
Step Input (Mappings):
Two mappings only - System ID (thing_id) and System Version (version_id) of the record to submit, sourced from a previous step or the workflow input.
Output (available to subsequent steps): System ID and System Version of the now-submitted record.
Execute Server Function
Section titled “Execute Server Function”Calls a published Server Function as a step in the workflow. This is the primary way a Database Workflow hands off work that needs external I/O, AI, file handling, or anything that can’t run inside PLV8.
Step Settings:
| Field | Description |
|---|---|
| Server Function | The Server Function to call |
| Method | Optional - the specific handler/command to invoke if the function exposes multiple public methods |
Step Input (Mappings):
Maps workflow context values into the function’s input structure.
Output (available to subsequent steps): whatever the Server Function returns, if it has an output structure defined or auto-discovered.
Execute Database Workflow
Section titled “Execute Database Workflow”Calls another published Database Workflow as a step. Works identically to Execute Server Function - same Settings fields (target workflow + optional method), same input mappings, same output handling.
Use this to compose reusable sub-workflows rather than duplicating logic across multiple workflows.
Expression
Section titled “Expression”Evaluates a PostgreSQL expression at runtime and makes the result available to subsequent steps as a single computed value.
Step Settings:
The Settings screen is the full configuration for this step - there is no separate Input screen.
A Calculation Formula code editor takes the expression. An Expand button opens it full-screen. A context helper panel on the right has four sections:
- STEPS - all previous steps in the workflow, expandable by name to browse their output fields. Workflow Input appears here too.
- SCALAR SQL FUNCTIONS - published scalar views callable as functions.
- DATASET SQL FUNCTIONS - published dataset views.
- POSTGRES FUNCTIONS - the full built-in PostgreSQL function library.
Click any item in the helper to insert a reference into the expression at the cursor.
Output (available to subsequent steps): the single computed value the expression returns.
Condition
Section titled “Condition”Evaluates a condition against the workflow context and routes execution to one of two paths.
Step Settings:
The condition builder is embedded in the Settings screen. Each condition row has:
| Field | Description |
|---|---|
| Operand 1 | A field from the workflow context (previous step output or Workflow Input) |
| Operator | Comparison operator - Equals, Contains, Greater Than, Is Empty, and others |
| Source Type | Value of (compare to another context field) or Fixed value (compare to a constant) |
| Value | The constant to compare against, when Source Type is Fixed value |
Complex nested conditions are supported via the Back navigation within the condition builder.
Output: none - Condition only routes, it does not produce a value.
Next Step: two paths - Next if True and Next if False, each independently pointing to another step or End.
Review
Section titled “Review”Pauses the workflow and routes a record to one or more reviewers for approval. When execution reaches a Review step, the workflow pauses and waits asynchronously until a reviewer acts. The workflow resumes only when approval or rejection is recorded.
Multiple Review steps in a single workflow implement a multi-stage approval policy.
Step Settings:
| Field | Description |
|---|---|
| Review Type | Any Reviewer - one approval from any listed reviewer is sufficient; All Reviewers - every listed reviewer must approve; Minimum Reviewers - a specified minimum number must approve |
| Minimum Number of Reviewers | Required when Review Type is Minimum Reviewers |
| Reviewers | One or more reviewer identities, added with + Add more |
Step Input (Mappings):
Two mappings - System ID (thing_id) and System Version (version_id) of the record being reviewed. In most cases these come directly from the workflow’s Input Structure, since workflows are typically triggered when a record is submitted.
Next Step: two paths:
- Next if approved - where to go when the review passes
- Next if rejected - where to go when rejected. This does not have to be End/Failed - it can route to another step (for example, a notification or a reset step) before eventually ending.
Foreach
Section titled “Foreach”Iterates over a collection of records - a component’s rows or a view’s result set - running a nested set of steps on each record in turn.
Step Settings:
| Field | Description |
|---|---|
| Record Type | Component or View (View can cover entities, components, or any other query result) |
| Component / View | The specific target to iterate over |
Step Input (Mappings):
Filter parameters for the Component or View - controls which records are included in the iteration. Same mapping structure as Lookup record.
The inner canvas:
Click the drill-into icon on a Foreach node (visible on hover) to enter the step’s inner canvas. The breadcrumb at the top updates to Main > [foreach step name] to show where you are.
The inner canvas is a full workflow canvas in its own right - the same empty state, the same + Add Step button, and the same nine step types. Build the steps that should run on each record here.
Within the inner canvas, the workflow context includes:
- Current record - the fields of the record in the current iteration
- Parent scope - all step outputs from the Main canvas that preceded this Foreach step
When a step inside the Foreach reaches End, it means only the current iteration is complete - execution moves to the next record. There is no Succeeded/Failed status, no message, and no output mappings on an inner End.
Next Step (outer): a single next step - where the workflow goes after all iterations have completed.
Workflow context
Section titled “Workflow context”Every step that produces output makes it available to all steps that come after it. When configuring any mapping, condition, or expression, the Source dropdown exposes:
- Workflow Input - the fields of the workflow’s Input Structure (if one was defined)
- Previous step outputs - each preceding step listed by name, expandable to its output fields
Steps can only reference steps that precede them in the execution flow. Referencing a later step will prevent the workflow from publishing.
Next Step configuration
Section titled “Next Step configuration”Every step ends with a Next Step panel - the final screen before saving the step. From here:
- Next Step - select any existing step to chain to, or select End to terminate this path
- + Add New Step - create a new step inline without going back to the canvas
When End is selected, two additional options appear:
| Field | Description |
|---|---|
| Status | Succeeded or Failed - marks the overall workflow execution outcome for this path |
| Message | Free text, surfaced to the caller - especially useful on Failed paths to explain what went wrong |
| Mappings | Map step output values to the workflow’s Output Structure fields - only available if the workflow was created with an Output Structure |
Condition and Review steps show this panel twice - once per path (True/False for Condition, Approved/Rejected for Review).
AI/Code mode
Section titled “AI/Code mode”The AI/Code tab is only available on workflows created with the AI/Code definition type. Design mode workflows use the Diagram tab instead and do not expose a code editor.
The interface works identically to the AI/Code mode on Server Functions - AI chat as the primary view, See Code to toggle to the code editor, Context picker to add entities/views/functions as AI context, and Apply to push AI suggestions into the editor.
The key difference from Server Functions: the code generated here is PLV8 (synchronous JavaScript running inside PostgreSQL), not Node.js. PLV8 is suited for short, transactional platform-data work - it does not support external HTTP calls, AI APIs, file operations, or long-running logic. For those, use an Execute Server Function step in your Design workflow, or choose a Server Function directly.
New AI/Code workflows start with a PLV8 template pre-populated in the editor (METADATA, CONSTANTS, PRIVATE_FUNCTIONS, HANDLERS structure). JSDoc on handlers works the same way - properly annotated handlers get their metadata extracted at publish time, powering the Published methods picker in Run Function and the method selector in workflow Execute Database Workflow steps.
Run Function and Logs work identically to Server Functions - see Running a function and Function logs.
For PLV8 API reference and code conventions, see Developer Reference - PLV8 Database Functions.
Security Rules
Section titled “Security Rules”Security Rules (top right of the detail view) controls who can execute this workflow. Each rule overrides the default access behaviour for a specific set of users or roles:
| Field | Description |
|---|---|
| Rule Name | Human-readable name for the rule |
| Access Level | Allow - the matched users/roles can execute this workflow; Forbid - they cannot |
| All Users | When checked, the rule applies to all users regardless of Security Dimensions |
| Security Dimensions | One or more User or Role entries the rule applies to. Use + Add more to add additional users or roles. |
Workflow Triggers
Section titled “Workflow Triggers”The Workflow Triggers card sits on the Details tab alongside the Workflow Details card. Click Edit to open the Workflow Triggers panel where you can add, edit, and remove triggers for this workflow.
A workflow can have zero, one, or more triggers. Each trigger defines one way the workflow can be invoked - either as an action button on entity records in the UI (Manual), or automatically on a recurring schedule (Scheduled).
Manual triggers
Section titled “Manual triggers”A Manual trigger makes the workflow available as an action button on records of the specified entities. When a user clicks that button, the workflow is invoked with the record’s identifiers passed into its input.
| Field | Description |
|---|---|
| Trigger Name | Human-readable name shown on the action button |
| Trigger ID | Auto-generated from the name |
| Entities | One or more entities whose records should show this trigger as an action. Use + Add more to add additional entities. |
| Mappings | Maps the triggering record’s identifiers to the workflow’s input structure fields. Target is a field on the workflow’s Input Structure (e.g. System ID, System Version); Source is the corresponding identifier from the triggering record. |
| Show Object | When checked: if the workflow’s output contains record identifiers, the platform automatically opens that record once the workflow completes. Useful when a workflow creates or transitions a record and you want the user to land on the result. |
| Icon | The icon displayed on the action button in the UI |
| Trigger Module | Which module this trigger belongs to |
| Trigger Description | Optional free text |
Scheduled triggers
Section titled “Scheduled triggers”A Scheduled trigger runs the workflow automatically on a cron schedule, without any user interaction.
| Field | Description |
|---|---|
| Trigger Name | Human-readable name |
| Trigger ID | Auto-generated from the name |
| Schedule Expression | A cron expression in 5-field format: Minutes, Hours, Day of month, Month, Day of week. Click the gear icon to open the Schedule Configuration helper. |
| Logging Level | What gets recorded when the scheduled run executes: No Logging, Errors Only, or Everything |
| Run As User | The user identity the workflow runs as (e.g. system_user). The workflow executes with this user’s permissions for access control and audit purposes. |
| Trigger Module | Which module this trigger belongs to |
| Trigger Description | Optional free text |
Schedule Configuration helper: clicking the gear icon on the Schedule Expression field opens a panel with:
- Quick Presets - one-click shortcuts: Every minute, Hourly, Daily, Weekly, Monthly. Selecting a preset fills in all five cron fields.
- Individual fields - Minutes, Hours, Day of month, Month, Day of week - for custom schedules not covered by a preset.
- Next Occurrences - once a valid expression is set, the panel shows the next several execution times in both GMT (server time) and LOCAL (UTC), so you can confirm the schedule fires when you expect before saving.
Where workflows go from here
Section titled “Where workflows go from here”A published Database Workflow is callable from anywhere in the platform that can invoke a function:
- As an Execute Database Workflow step inside another workflow - enabling reusable sub-workflows.
- From a Server Function via
api.execute_function- useful when a Node process needs to delegate transactional data work back into PLV8. - From Triggers - to run automatically in response to record changes, on a schedule, or other system events.
- From the UI via Portal Components - as an action a user triggers directly.