← Back to all posts
12 min readCentrali Team

Building Multi-Step Workflows: A Practical Guide to Centrali Orchestration

Learn how to build production-ready workflows with Centrali Orchestration. This guide covers order processing, approval flows, and data synchronization patterns with real examples.

GuidesTutorialorchestration

Centrali's new Workflow Orchestration feature makes it easy to build complex, multi-step processes. In this guide, we'll walk through three common patterns: order processing, approval workflows, and data synchronization.

Prerequisites

Before we begin, make sure you have:

  • A Centrali workspace (v2.9.0 or later)
  • Some compute functions ready to use (or we'll create them)
  • Basic familiarity with the Centrali console

Pattern 1: Order Processing Pipeline

Let's build an order processing workflow that validates orders, processes payments, and sends confirmations.

Step 1: Create the Orchestration

Navigate to Orchestrations and click + Orchestration:

  • Name: Complete Order Processing Pipeline
  • Slug: complete-order-processing-pipeline
  • Trigger Type: Event (record created on your orders structure)

Step 2: Add the Validation Step

Click Add Step and choose Compute Step:

Step ID: validate-order
Step Name: Validate Order
Compute Function: [Select your validation function]
Timeout: 30000ms

Your validation function should return an object like:

javascript
// Validation function example async function validateOrder(input, api) { const order = input.data; // Check inventory const inventory = await api.records.list('inventory', { filters: { productId: order.productId } }); if (inventory[0]?.quantity < order.quantity) { return { isValid: false, error: 'Insufficient inventory' }; } // Validate shipping address if (!order.shippingAddress?.zipCode) { return { isValid: false, error: 'Invalid shipping address' }; } return { isValid: true, order }; }

Step 3: Add a Decision Step

After validation, we need to check if the order is valid:

Step ID: check-validation
Step Name: Check Validation Result
Type: Decision Step

Add a case:

  • Condition: steps.validate-order.output.isValid equals true
  • Then go to: process-payment

Set the default (no case matches) to go to handle-validation-error.

Step 4: Add Payment Processing

Step ID: process-payment
Step Name: Process Payment
Compute Function: [Select your payment function]
Timeout: 60000ms

Step 5: Add Error Handling

Step ID: handle-validation-error
Step Name: Handle Validation Error
Compute Function: [Select your error handling function]

This function can update the order status and notify the customer.

Step 6: Add Confirmation

Step ID: send-confirmation
Step Name: Send Confirmation
Compute Function: [Select your email function]

Complete Workflow

Your workflow should look like this:

[Event: Order Created]
        ↓
[Validate Order]
        ↓
[Check Validation] ──(invalid)──→ [Handle Error]
        ↓ (valid)
[Process Payment]
        ↓
[Send Confirmation]

Pattern 2: Approval Workflow with Timeout

Let's build a leave request approval system with a 48-hour timeout.

Step 1: Create the Orchestration

  • Trigger Type: On-Demand (requests submitted via API)

Step 2: Notify the Approver

Step ID: notify-approver
Step Name: Notify Approver
Compute Function: [Select your notification function]

The function receives the leave request data and sends an email to the manager.

Step 3: Add a Delay Step

Step ID: wait-for-response
Step Name: Wait for Response
Type: Delay Step
Delay Duration: 172800000ms (48 hours)

Note: In a real system, you'd want to check for approval status periodically or use a webhook callback. For this example, we're simulating a wait period.

Step 4: Check Approval Status

Step ID: check-approval
Step Name: Check Approval Status
Compute Function: [Select your status check function]

This function queries the request record to see if it was approved:

javascript
async function checkApprovalStatus(input, api) { const requestId = input.requestId; const request = await api.records.get('leave-requests', requestId); return { status: request.data.approvalStatus, approved: request.data.approvalStatus === 'approved', requestId }; }

Step 5: Decision Based on Status

Step ID: route-by-status
Type: Decision Step

Cases:

  • steps.check-approval.output.status equals approvedexecute-approved
  • steps.check-approval.output.status equals rejectednotify-rejection
  • Default → escalate (timeout reached, no response)

Step 6: Handle Each Path

Add compute steps for:

  • execute-approved — Update calendar, send confirmation
  • notify-rejection — Notify the requester of rejection
  • escalate — Notify HR of unhandled request

Pattern 3: Data Synchronization

Let's build a workflow that syncs customer data to an external CRM when records are updated.

Step 1: Create the Orchestration

  • Trigger Type: Event (record updated on customers structure)

Step 2: Transform Data

Step ID: transform-data
Step Name: Transform to CRM Format
Compute Function: [Select your transform function]
javascript
async function transformToCRM(input, api) { const customer = input.data; // Map Centrali fields to CRM fields return { crmPayload: { external_id: customer.id, first_name: customer.firstName, last_name: customer.lastName, email: customer.email, company: customer.companyName, phone: customer.phone, custom_fields: { plan_type: customer.subscriptionTier, signup_date: customer.createdAt } } }; }

Step 3: Push to External API

Step ID: push-to-crm
Step Name: Push to CRM
Compute Function: [Select your API function]
Timeout: 30000ms
javascript
async function pushToCRM(input, api) { const payload = input.crmPayload; const response = await fetch('https://api.crm.example.com/contacts', { method: 'POST', headers: { 'Authorization': 'Bearer ' + process.env.CRM_API_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`CRM API error: ${response.status}`); } const result = await response.json(); return { success: true, crmId: result.id }; }

Important: The orchestration engine will automatically retry failed steps with exponential backoff, making your sync resilient to temporary API failures.

Step 4: Log the Result

Step ID: log-sync
Step Name: Log Sync Result
Compute Function: [Select your logging function]

This creates an audit trail of all syncs.

Tips for Production Workflows

1. Use Meaningful Step IDs

Step IDs are used in decision conditions and debugging. Use descriptive names like validate-shipping-address instead of step-1.

2. Configure Timeouts Appropriately

  • Fast operations (database queries): 5-10 seconds
  • API calls: 30-60 seconds
  • Complex processing: 2-5 minutes

3. Handle Errors Gracefully

Always plan for failures:

  • Use decision steps to check for error states
  • Add error handling steps that notify operators
  • Consider retry strategies for transient failures

4. Monitor Your Runs

Check the Runs tab regularly:

  • Look for failed runs and investigate root causes
  • Monitor execution times to identify bottlenecks
  • Use the Activity Log to understand timing

5. Test with On-Demand Triggers

Before enabling event or scheduled triggers:

  1. Create a version of your orchestration with an on-demand trigger
  2. Test with sample data
  3. Verify each step executes correctly
  4. Switch to the production trigger type

Summary

Centrali Orchestration makes it straightforward to build complex workflows:

  • Order processing — Chain validation, payment, and notification steps
  • Approval flows — Use delay steps and decisions for human-in-the-loop processes
  • Data sync — Leverage automatic retry for reliable integrations

Check out the Orchestration documentation for more details and API reference.

Building something with Centrali and want to share feedback about this feature?

Email feedback@centrali.io