Skip to main content

Workflow Architecture 101: Trigger, Transform, Publish

The component reference describes every building block on its own. This guide is about how they fit together: the mental model to have in your head before you add the first step, and the few workflow shapes that cover most real integrations.

The mental model​

Almost every integration workflow has three parts:

Every integration workflow has three parts in order: a source or trigger decides where data comes from and when, a transformation reshapes, filters, enriches and validates it, and a publisher delivers it where it needs to end up.

PartJobTypical components
Source / triggerDecide when the workflow runs and what data it starts withTrigger, plus reading components such as REST API (get), M3 API, Data Lake, File Loader
TransformationTurn the data you have into the data the next system needsTransform, Converter, and as a last resort Code
PublisherDeliver the resultREST API (post/put/patch), Table Updater, Email, SMS, Excel

Keeping these jobs apart is the single most useful habit in workflow design. A REST API step that only calls, a Transform that only reshapes, and a Table Updater that only stores are each easy to read, easy to test in Execution Logs, and easy to change without breaking the others.

tip

When a workflow is hard to understand, it is usually because one step is doing two jobs — for example a Code step that fetches, maps and posts all at once. Split it along the three parts above.

How data moves between steps​

Steps run in order, and by default each step works on the output of the step before it:

  • In a REST API step, {{ body.fieldName }} (and {{{ body.fieldName }}} in Endpoint URL) reads from that output.
  • In a Transform step, $ is that output. After a REST API step, that means $.statusCode, $.body and $.headers.

In a workflow with more than a few steps, though, it gets hard to see which step really is "the one before". So we recommend reading data through $context instead, naming the step you mean, even when it is the previous one:

ExpressionGives you
$context.data.trigger.bodyThe data the workflow was started with
$context.data.all.rest_api_1.bodyThe body returned by the step with ID rest_api_1

A step's ID is its type and a number, such as rest_api_1 or transform_2. See How step IDs are formed. An expression that names its steps can be read on its own, keeps working when steps are added or moved, and works the same when you test it in the Transform editor. The $context Reference lists everything else $context holds.

The proven shapes​

You rarely need to invent a workflow structure from scratch. These shapes cover the large majority of integrations built on Vince Platform.

1. Build – call – unwrap​

Build, call, unwrap: a trigger starts the workflow, a Transform builds the request, a REST API step sends it, and a second Transform unwraps the response.

The most common integration shape on the platform. The first Transform builds exactly the request the other system expects, the REST API step sends it without any mapping logic of its own, and the second Transform turns the response into clean fields (and checks statusCode, because a failed request does not stop the workflow).

Use it for: pushing an order to a warehouse system, creating a customer in a CRM, looking up prices from a pricing service.

See REST API in Practice for worked stories of this shape, and Combine M3 API Calls for an Infor M3 example.

2. Land, then react​

Land, then react: workflow A runs Trigger, Transform and Table Updater that writes records to a table; the change in that table fires the Event trigger of workflow B, which runs Transform and REST API.

Instead of one long workflow that fetches, transforms, sends and notifies, split the work at a table. Workflow A only lands data in a table. Writing the table fires an Event trigger, and workflow B reacts to exactly the change that happened — for example "status changed to Released".

Why it works well:

  • Decoupling — workflow A doesn't know who reacts. Add a second reacting workflow (an alert, an export) later without touching A.
  • A queryable seam — the table is a live record of what has flowed through. When something looks wrong, look at the table.
  • A natural retry point — if workflow B fails, the row is still there.

See Triggers in Depth for event expressions, and Designing Tables for how to shape the table itself.

3. Scheduled snapshot​

Scheduled snapshot: a Schedule trigger runs a Data Lake query, a Transform reshapes the rows and a Table Updater stores them.

Run a Data Lake query on a schedule, reshape the rows, and store them in a table. The table then serves apps, dashboards and other workflows quickly, without each of them querying the Data Lake on its own.

Use it for: nightly stock or open-order snapshots, reference data that changes slowly.

4. User-driven (Manual trigger and VXL Live)​

User-driven: a Manual trigger with input fields starts an M3 API or REST API step, and the result is returned to Excel through VXL Live.

A person starts the workflow — from the platform or from Excel through VXL Live — and fills in input fields on the Manual trigger. The workflow reads or updates data and returns the result to the user. See Export REST API Data to VXL Live for an example.

5. Notify at the end​

Notify at the end: after the earlier steps, a Transform builds the summary and an Email step sends it.

Any of the shapes above can end with a notification. Build the message content in a Transform first, then let the Email step only send it. See Email a Workflow Run Summary.

One workflow or several?​

Split into multiple workflows when:

  • Different things should happen at different times. Landing data hourly and sending it on change are two schedules — use land-then-react.
  • Several consumers need the same data. Land it once in a table; let each consumer react on its own.
  • Part of the work must be reusable. A workflow can be called synchronously as an API — see Combine M3 API Calls.

Keep it as one workflow when the steps always run together and the caller needs the final result straight away.

Where Code fits​

Code is the escape hatch: JavaScript for anything the other components can't express — for example protocols such as SFTP or SQL Server, or signing a request in a custom way. Reach for it deliberately, not by default:

  • A Transform is easier to read, needs no async handling, and covers most reshaping — see the JSONata Masterclass.
  • A REST API step shows the request and response clearly in Execution Logs. Calls hidden inside Code don't.
  • When you do use Code, keep it to one job, and return the values you need to debug — console.log output is not shown in the execution view.

Checklist for a new workflow​

  1. Write down the three parts: what starts it, what reshaping is needed, where the result goes.
  2. Pick the closest proven shape above.
  3. Give each step one job.
  4. Check every REST API response's statusCode in the Transform that follows it.
  5. Run it, then read each step's output in Execution Logs before adding the next step.

Further reading​