Hero image for From Solo Bot to Robot Army: Mastering UiPath Orchestrator and Queue Patterns

From Solo Bot to Robot Army: Mastering UiPath Orchestrator and Queue Patterns

RPA UiPath Orchestrator Queues Enterprise Automation

Your first bot runs on your machine. It processes 100 invoices a day. Everyone’s happy.

Then the request comes: “Can we do 10,000 invoices?”

The answer isn’t to make your bot run faster. It’s to make it run in parallel, across multiple machines, with centralized control.

Welcome to orchestration.


Getting Started: Access Your Free Orchestrator

Common Myth: “I don’t have Orchestrator, so I can’t learn Queue patterns and enterprise architecture.”

Reality: You do have access! It’s in the cloud, and it’s free forever.

Scenario A: Individual Learners (Most Common)

UiPath provides Community Edition, which is permanently free and has nearly identical functionality to the Enterprise version (only limited by robot count).

How to Get Your Free Orchestrator:

graph LR
    %% 標題:用圓形,文字強制分三行
    Start(("Free<br/>Orchestrator<br/>Setup<br/>"<br/>))

    %% Step 1: 縮短單行長度
    Step1["<b>Step 1:</b><br/>No Install<br/>Required<br/>---------<br/>It's a website,<br/>not software<br/>"<br/>]
    
    %% Step 2
    Step2["<b>Step 2:</b><br/>Register<br/>-----------<br/>Create acct on<br/>cloud.uipath.com<br/><br/>"]
    
    %% Step 3
    Step3["<b>Step 3:</b><br/>Login<br/>-----------<br/>Click<br/>'Default Tenant'"]
    
    %% Step 4: 這是關鍵步驟,字最多,切最細
    Step4["<b>Step 4:</b><br/>Connect Studio<br/>-----------<br/>Pair local PC<br/>with Cloud<br/>(Critical!)"]

    %% 連線
    Start --> Step1
    Step1 --> Step2
    Step2 --> Step3
    Step3 --> Step4

    %% 樣式設定:增加內部填充 (padding) 防止文字貼邊
    classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px,rx:5,ry:5,text-align:center;
    
    %% 特別強調 Step 4
    style Step4 fill:#ffe6e6,stroke:#f00,stroke-width:2px

Connection Steps:

  1. Open UiPath Assistant (green robot icon in system tray)
  2. PreferencesOrchestrator Settings
  3. Select Service URL mode
  4. Sign in with your UiPath account
  5. Verify status: Should show green Connected, Licensed ?

Now you can use Queues and Assets! This is the only way to learn enterprise-grade architecture.


Scenario B: Corporate Environment Without Orchestrator

If you’re on a closed corporate network, or your company only has Standalone licenses without internet access, then you “temporarily” won’t have Orchestrator.

Interview Question: “Can REFramework run without Orchestrator?”

Answer: Yes, but the mode changes.

REFramework Fallback Mode:

With OrchestratorWithout Orchestrator (Fallback)
Get Transaction Item fetches from QueueRead from local Excel file
TransactionItem type is QueueItemChange to DataRow (Excel) or String (filenames)
Config.xlsx stores Queue NameStore Excel file path instead
Auto-retry managed by QueueMust implement retry logic manually

Fallback Configuration Steps:

' 1. In Main.xaml, find variable TransactionItem
'    Original type: UiPath.Core.QueueItem
'    Change to: System.Data.DataRow

' 2. In GetTransactionData.xaml
'    Original: Get Transaction Item activity
'    Change to: Read current Row from DataTable

' 3. In Config.xlsx
'    Original: OrchestratorQueueName = "Invoice_Processing"
'    Change to: InputExcelPath = "C:\Data\Invoices.xlsx"

Important: Fallback mode is only suitable for development/testing. In production without Orchestrator, you lose:

  • Automatic retry and failure management
  • Multi-robot parallel processing
  • Centralized monitoring and reporting
  • Secure credential storage (Assets)

The Limits of Single-Machine Automation

Before we dive into solutions, let’s understand the problem.

The Solo Bot Ceiling

ConstraintImpact
Processing speedOne bot = one item at a time
Machine dependencyIf the PC crashes, everything stops
No schedulingManual start/stop, no off-hours running
No visibilityNo dashboard, no real-time monitoring
Credential storagePasswords in code or local files
No work distributionCan’t split tasks across machines

At some point, you need infrastructure. That infrastructure is Orchestrator.


What is Orchestrator?

UiPath Orchestrator is a web-based platform for managing, monitoring, and scaling your automation fleet.

Think of it as:

  • Air Traffic Control for robots
  • Job Scheduler on steroids
  • Credential vault for sensitive data
  • Analytics dashboard for performance metrics

Core Components

%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '16px'}}}%%
graph TD
    %% 主標題節點 (用 HTML 放大)
    MainTitle["<span style='font-size:26px; font-weight:bold'>🚀 UiPath Orchestrator<br/></span>"]

    %% 外框
    subgraph UO [System Overview]
        direction TB

        %% 上層:四大功能
        subgraph Manage [Management Layer]
            direction LR
            R["<span style='font-size:20px'>🤖</span><br/>Robots<br/><br/>"]
            Q["<span style='font-size:20px'>📥</span><br/>Queues<br/><br/>"]
            A["<span style='font-size:20px'>🔐</span><br/>Assets<br/><br/>"]
            S["<span style='font-size:20px'>⏰</span><br/>Schedules<br/><br/>"]
        end

        %% 下層:執行區塊
        subgraph Exec [Execution Layer]
            direction TB
            B1[Bot 1]
            B2[Bot 2]
            B3[Bot 3]
            B4[Bot 4]
            B5[Bot 5]
        end

        %% 連接
        R & Q & A & S ==> Exec
    end

    %% 連接標題
    MainTitle --- UO

    %% 樣式
    style MainTitle fill:#fff,stroke:none
    style UO fill:#f0f4f8,stroke:#333,stroke-width:2px
    style Exec fill:#e1f5fe,stroke:#0277bd,stroke-width:2px,stroke-dasharray: 5 5

Key Terms

TermDefinition
RobotThe software agent that executes automation (UiPath Robot)
MachineThe physical/virtual PC where a robot runs
ProcessA published automation package (your .nupkg file)
JobAn instance of a process running on a robot
QueueA collection of work items to be processed
Queue ItemA single unit of work (e.g., one invoice)
AssetA stored value (credentials, config settings)
TriggerCondition that starts a job (schedule, queue, event)
FolderOrganizational unit for robots, processes, queues, and assets

Modern Folders vs Classic Folders

Important: As of 2021, Modern Folders are the default and recommended approach in UiPath Orchestrator. Understanding this distinction is critical for new implementations.

The Architecture Shift

graph TD
    %% --- 設定樣式 ---
    classDef legacy fill:#f9f9f9,stroke:#999,stroke-width:2px,stroke-dasharray: 5 5;
    classDef classicFolder fill:#ffebee,stroke:#c62828,stroke-width:2px;
    classDef modern fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
    classDef tenant fill:#fff3e0,stroke:#ef6c00,stroke-width:2px;
    classDef bot fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px,rx:5,ry:5;
    classDef noteBox fill:#fff,stroke:#333,stroke-width:1px,stroke-dasharray: 2 2;

    %% ==============================
    %% 左側:Classic Folders (Legacy)
    %% ==============================
    subgraph ClassicWrapper ["❌ CLASSIC FOLDERS (Legacy)"]
        direction TB
        
        %% Header 區
        subgraph C_Header [Concept]
            direction LR
            Note1["Feature: Robots belong to FOLDER<br/>"]
            Warning["⚠️ Constraint: One robot = ONE folder<br/>"]
        end

        %% 結構圖
        subgraph CFA ["📁 Folder A"]
            CB1[Bot 1]
            CB2[Bot 2]
        end

        subgraph CFB ["📁 Folder B"]
            CB3[Bot 3]
            CB4[Bot 4]
        end

        %% 連線
        C_Header ==> CFA
        CFA ~~~ CFB
    end

    %% ==============================
    %% 右側:Modern Folders (Current)
    %% ==============================
    subgraph ModernWrapper ["✅ MODERN FOLDERS (Current)<br/>"]
        direction TB
        
        %% Header 區
        subgraph M_Header [Concept]
            direction LR
            Note2["Feature: Robots belong to TENANT<br/>"]
            Success["✨ Benefit: Full Utilization<br/>"]
        end

        %% 結構圖
        subgraph Tenant ["🏢 Tenant Resource Pool"]
            direction TB
            MB1[Bot 1]
            MB2[Bot 2]
            MB3[Bot 3]
            MB4[Bot 4]
        end

        subgraph AccessScope ["Folders = Access Scope"]
            direction LR
            MFA["📁 Folder A"]
            MFB["📁 Folder B"]
        end

        %% 連線
        M_Header ==> Tenant
        Tenant ==> MFA
        Tenant ==> MFB
    end

    %% 套用樣式
    class ClassicWrapper legacy;
    class CFA,CFB classicFolder;
    class ModernWrapper modern;
    class Tenant tenant;
    class CB1,CB2,CB3,CB4,MB1,MB2,MB3,MB4 bot;
    class Warning classicFolder;
    class Success modern;
    class C_Header,M_Header noteBox;

Key Differences

AspectClassic FoldersModern Folders
Robot assignmentRobot belongs to one folder onlyRobots at tenant level, shared across folders
Machine definitionMachine Template + Robot = LicenseMachine Template with dynamic allocation
Unattended licensingPer-robot license assignmentFloating license pool
Personal workspaceNot supportedEach user gets personal folder
Robot accountsWindows accounts requiredRobot Accounts (no Windows user needed)
Folder hierarchyFlat structureSubfolders supported
Concurrent jobsLimited by robot-folder bindingFlexible based on license pool

Why Modern Folders Matter

1. Better Resource Utilization

Classic:

Folder A: Bot1, Bot2 (only run Folder A processes)
Folder B: Bot3, Bot4 (only run Folder B processes)
→ If Folder A is idle, Bot1 and Bot2 can't help Folder B

Modern:

Tenant: Bot1, Bot2, Bot3, Bot4 (available to any folder)
Folder A: Process X (can use any available bot)
Folder B: Process Y (can use any available bot)
→ Full utilization: any bot can run any folder's work

2. Robot Accounts (No Windows User Required)

Classic: Unattended robot needs Windows login
  └── Create Windows AD account for each robot
  └── Manage passwords, group policies
  └── Security and compliance overhead

Modern: Robot Account in Orchestrator
  └── No Windows account needed
  └── Managed entirely in Orchestrator
  └── Simpler compliance, no AD dependency

3. Dynamic License Allocation

Classic (Static):
  License 1 → Bot1 (always assigned)
  License 2 → Bot2 (always assigned)
  → 2 licenses, max 2 concurrent jobs

Modern (Floating Pool):
  License Pool: 2 Unattended Runtime licenses
  Job request → Allocate from pool → Release after job
  → Same 2 licenses, but more flexible distribution

Migration Considerations

If you’re working with an existing Classic Folders setup:

SituationRecommendation
New Orchestrator setupAlways use Modern Folders
Existing Classic, works fineCan continue, but plan migration
Scaling beyond current limitsMigrate to Modern Folders
Need subfolders/hierarchyMust use Modern Folders
Using Automation CloudModern Folders only

Creating a Modern Folder

When creating a new folder in Orchestrator:

  1. Navigate to Tenant → Folders → Add Folder
  2. Ensure “Use Modern Folders” is enabled (tenant setting)
  3. Assign processes, queues, and assets to the folder
  4. Grant robot access via Roles (not direct assignment)
Folder Settings:
├── Name: "Invoice_Processing"
├── Parent: (None or select parent folder)
├── Assigned Processes:
│   ├── Invoice_Dispatcher
│   └── Invoice_Performer
├── Assigned Queues:
│   └── Invoice_Queue
├── Assigned Assets:
│   ├── SAP_Credentials
│   └── EmailRecipients
└── Role Assignments:
    ├── RPA_Developers: Edit
    ├── RPA_Operators: Execute
    └── Robot_ServiceAccount: Robot (execute jobs)

Queues: The Heart of Scalable RPA

Queues are what enable true scalability. Instead of one bot processing a list sequentially, you:

  1. Load all work items into a queue
  2. Multiple bots pull items from the queue
  3. Each bot processes independently
  4. Results are tracked centrally

Queue Item Lifecycle

stateDiagram-v2
    %% 設定標題 (雖然 stateDiagram 原生不支援標題,但我用註解標示)
    %% Title: Queue Item States

    %% 初始狀態
    [*] --> New: Add Item
    
    %% 主要轉換
    New --> InProgress: Get Transaction Item
    
    %% In Progress 的三種結果
    state InProgress {
        %% 這裡可以加上備註,雖然 Mermaid 顯示會有差異
        direction LR
        [*] --> Processing
    }

    InProgress --> Successful: Set Transaction Status (Success)<br/><br/>
    InProgress --> Failed: Set Transaction Status (System/Business Exception)<br/><br/>
    InProgress --> Abandoned: 24h Timeout (No Status Set)<br/><br/>

    %% 關於 Retry 的特殊路徑
    Failed --> Retried: If Retry Enabled & MaxRetry > 0<br/><br/>
    Retried --> New: System auto-creates new item<br/><br/>

    %% 最終狀態
    Successful --> [*]
    Abandoned --> [*]
    
    %% 樣式設定
    classDef success fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
    classDef fail fill:#ffebee,stroke:#c62828,stroke-width:2px;
    classDef progress fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
    classDef new fill:#fff3e0,stroke:#ef6c00,stroke-width:2px;
    
    class Successful success
    class Failed,Abandoned,Retried fail
    class InProgress progress
    class New new

State Definitions

StateMeaning
NewItem is waiting to be processed
In ProgressA robot has claimed it and is working
SuccessfulProcessing completed successfully
FailedProcessing failed (business or system exception)
AbandonedRobot crashed or timed out mid-processing
RetriedFailed item that was cloned for retry (see below)

Understanding Retry Behavior: The Cloning Mechanism

Critical for Reporting: This behavior is often misunderstood and causes reporting errors.

When an item fails and is automatically retried, Orchestrator does not simply revert the item to “New” status. Instead:

  1. The original item status changes to “Retried” (counted as a failure type)
  2. A brand new clone item is created with status “New”
  3. The clone has a new Queue Item ID but same Reference and SpecificContent
sequenceDiagram
    participant O as Original Item (12345)
    participant C as Clone Item (12346)
    
    Note over O: Status: New
    Note over O: Status: In Progress
    
    rect rgb(255, 200, 200)
    Note over O: ❌ Fails
    end
    
    O->>C: Orchestrator Auto-Retry
    
    par Update Old Item
        Note over O: Status: Retried
        Note over O: (End of Life)
    and Create New Item
        Note over C: Status: New
        Note over C: Status: In Progress
        rect rgb(200, 255, 200)
        Note over C: ✅ Successful
        end
    end

Why This Matters for Reporting:

If you’re calculating total transactions processed:

' WRONG: Counts both original and clone
totalProcessed = queue.Items.Count()  ' Returns 2 for same transaction!

' CORRECT: Count unique references, or exclude "Retried" status
successfulUnique = queue.Items _
    .Where(Function(i) i.Status = "Successful") _
    .Count()

' Or count only final states (excluding Retried which is intermediate)
finalStates = queue.Items _
    .Where(Function(i) i.Status <> "Retried") _
    .GroupBy(Function(i) i.Reference) _
    .Count()

Best Practice for Analytics Queries:

MetricHow to Calculate
Transactions attemptedCount where Status NOT IN (“Retried”)
Success rateSuccessful / (Successful + Failed) — exclude Retried
Total retriesCount where Status = “Retried”
Items requiring 2+ attemptsItems with any “Retried” record

Dead Letter Queue: Handling Poison Messages

When an item exhausts all retries and still fails, it becomes a “poison message”—it will never be processed unless someone intervenes manually.

[!CAUTION] UiPath doesn’t have a built-in Dead Letter Queue, but you should implement one:

Recommended Pattern:

' In SetTransactionStatus (when marking as Failed for the LAST time)
If transactionItem.RetryNo >= Config("MaxRetryNumber") Then
    ' This is the final failure - trigger Dead Letter handling
    
    ' Option 1: Send notification email
    SendEmail(
        To: Config("OpsTeam_Email"),
        Subject: $"[POISON] Item {transactionItem.Reference} exhausted retries",
        Body: $"Please investigate manually. Error: {exceptionMessage}"
    )
    
    ' Option 2: Log to Exception Dashboard
    InsertDBRecord("RPA_DeadLetterLog", 
        Reference: transactionItem.Reference,
        Queue: queueName,
        ErrorMessage: exceptionMessage,
        Timestamp: DateTime.Now
    )
    
    ' Option 3: Add to a separate "DeadLetter" queue for manual review
    AddQueueItem("Invoice_DeadLetter", transactionItem.SpecificContent)
End If

Why This Matters: Without Dead Letter handling, failed items silently disappear into “Failed” status, and operations staff has no proactive notification.

Queue Item Properties

Each queue item can carry:

  • Specific Content: Custom fields (JSON) with your business data
  • Reference: Unique identifier for tracking
  • Priority: High, Normal, Low
  • Deadline: When must this be processed by?
  • Postpone: Don’t process until this timestamp
  • Output: Results after processing
  • Analytics: Timing, retry count, robot ID

The Dispatcher-Performer Pattern

This is the architectural pattern that unlocks true scalability.

Concept

Split your automation into two separate processes:

  1. Dispatcher: Reads source data, creates queue items
  2. Performer: Processes queue items one at a time
flowchart TD
    %% 定義區域
    subgraph Input_Layer [Data Layer]
        DS[Data Sources<br/>Excel, DB, API]
    end

    subgraph Robot_Environment [Robot Execution Environment]
        Disp(Dispatcher Robot):::bot
        Perf1(Performer Robot 1):::bot
        Perf2(Performer Robot 2):::bot
    end

    subgraph Orchestrator_Layer [Orchestrator Server]
        Queue[("Transaction Queue")]:::infra
    end
    
    subgraph App_Layer [Application Layer]
        Target[Target App]:::app
    end

    %% 邏輯流
    DS ==> Disp
    Disp -.->|Upload Items| Queue
    Queue -.->|Fetch Item| Perf1
    Queue -.->|Fetch Item| Perf2
    Perf1 ==> Target
    Perf2 ==> Target

    %% 樣式
    classDef bot fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,rx:5,ry:5;
    classDef infra fill:#ffccbc,stroke:#d84315,stroke-width:2px,shape:cylinder;
    classDef app fill:#cfd8dc,stroke:#455a64,stroke-width:2px;

Why Separate Them?

BenefitExplanation
ScalabilityAdd more Performer robots without changing Dispatcher
ResilienceIf one Performer crashes, others continue. Queue persists.
VisibilityQueue shows exactly how much work remains
Retry handlingFailed items requeue automatically
Different schedulesDispatcher runs once/day, Performers run continuously
Different machinesDispatcher on scheduler, Performers on farm

The Math of Parallel Processing

Why do we need multiple robots? Here’s the formula:

Total Time=N×TitemR\text{Total Time} = \frac{N \times T_{item}}{R}

Where:

  • N = Total number of items to process
  • T_item = Average time to process one item
  • R = Number of robots

Example:

Items: 10,000 invoices
Time per item: 2 minutes
Robots: 1

Total Time = (10,000 → 2) / 1 = 20,000 minutes = 333 hours - 14 days!

With 5 robots:
Total Time = (10,000 → 2) / 5 = 4,000 minutes = 67 hours - 2.8 days

With 10 robots:
Total Time = (10,000 → 2) / 10 = 2,000 minutes = 33 hours - 1.4 days

When N grows to enterprise scale, optimizing T_item has limits. The most effective lever is increasing R—hence the Dispatcher-Performer pattern.

Dispatcher Implementation

The Dispatcher is typically simple:

' Pseudo-code for Dispatcher

' 1. Read data source
invoiceData = ReadExcel("Invoices.xlsx")

' 2. For each item, add to queue
For Each row In invoiceData.Rows
    queueItem = New QueueItem()
    queueItem.Reference = row("InvoiceNumber")
    queueItem.Priority = If(row("Urgent") = "Yes", "High", "Normal")
    queueItem.SpecificContent = New Dictionary(Of String, Object) From {
        {"InvoiceNumber", row("InvoiceNumber")},
        {"Vendor", row("Vendor")},
        {"Amount", row("Amount")}
    }
    
    Orchestrator.AddQueueItem("Invoice_Processing", queueItem)
Next

Log.Info($"Dispatcher complete. Added {invoiceData.RowCount} items to queue.")

Performer Implementation

The Performer uses REFramework (see article 1):

' Get Transaction Data state
transactionItem = Orchestrator.GetQueueItem("Invoice_Processing")

If transactionItem Is Nothing Then
    ' Queue empty - end process
Else
    ' Process Transaction state
    invoiceNumber = transactionItem.SpecificContent("InvoiceNumber")
    vendor = transactionItem.SpecificContent("Vendor")
    amount = transactionItem.SpecificContent("Amount")
    
    ' ... do actual processing ...
    
    ' On success
    Orchestrator.SetTransactionStatus(transactionItem, "Successful", "Invoice processed")
    
    ' On failure
    Orchestrator.SetTransactionStatus(transactionItem, "Failed", "Vendor not found")
End If

Queue Configuration Deep Dive

Creating a Queue

When you create a queue in Orchestrator, you configure:

SettingPurposeRecommendation
NameUnique identifier{Process}_{DataType}, e.g., Invoice_Processing
Max # of retriesAuto-retry on failure2-3 for transient failures
Auto RetryRetry on any exception?Yes for system, No for business
Unique ReferencePrevent duplicatesYes, using invoice/transaction ID
SLATarget processing timeBased on business requirements

Unique Reference: Preventing Duplicates

If you enable unique references:

' First add - succeeds
AddQueueItem(queue, reference: "INV-001", content: {...})  ' ?

' Duplicate add - silently ignored
AddQueueItem(queue, reference: "INV-001", content: {...})  ' Skipped

' Different reference - succeeds
AddQueueItem(queue, reference: "INV-002", content: {...})  ' ?

This prevents reprocessing if the Dispatcher runs multiple times.

Priority and Deadlines

' High priority - processed first
item1 = New QueueItem()
item1.Priority = QueueItemPriority.High
item1.Deadline = DateTime.Now.AddHours(2)  ' Must complete by 2 hours

' Normal priority  
item2 = New QueueItem()
item2.Priority = QueueItemPriority.Normal

' Postponed - don't process until specific time
item3 = New QueueItem()
item3.Postpone = DateTime.Today.AddHours(18)  ' Process after 6 PM

Queue processing order:

  1. Deadline approaching (urgent)
  2. Priority (High > Normal > Low)
  3. Creation time (FIFO within same priority)

[!TIP] Postpone: Smarter Than Retry
Use Postpone when the failure is predictable and temporary, not random.

Real Scenario: A bank transfer bot runs at 11 PM and hits a “System Maintenance” page. This isn’t a System Exception (retry won’t help)—the bank is always down 11 PM–6 AM.

' Instead of throwing exception and wasting retry attempts:
If maintenancePageDetected Then
    ' Postpone to next business window
    Dim nextMorning As DateTime = DateTime.Today.AddDays(1).AddHours(8)
    PostponeTransactionItem(transactionItem, nextMorning, "Bank maintenance window")
    ' Item returns to queue with New status, deferred until 8 AM
End If

This preserves retry count for actual failures, and the item automatically reprocesses when the system is available.


Assets: Secure Configuration

Assets store values that your automation needs but shouldn’t be hardcoded.

Asset Types

TypeUse CaseExample
TextSimple stringsQueue name, URL, email
IntegerNumeric configRetry count, timeout
BooleanFeature flagsSendNotifications = True
CredentialUsername + PasswordSAP login, DB connection

Why Use Assets?

  1. Security: Credentials are encrypted, never visible in code
  2. Environment separation: Different values for Dev/UAT/Prod
  3. No redeployment: Change values without republishing
  4. Audit trail: Track who changed what, when

Using Assets in Code

' Get credential
sapCredential = GetCredential("SAP_ServiceAccount")
username = sapCredential.Username
password = sapCredential.Password

' Get simple value
maxRetries = GetAsset("MaxRetryCount")  ' Returns: 3
emailRecipient = GetAsset("AlertEmail")  ' Returns: "ops@company.com"

[!CAUTION] Security Rule: Never Store Credentials as Text Assets
While you can store passwords as Text type Assets, you absolutely should not:

Asset TypeStorageSecurity
TextPlaintext in database? Visible to admins, in backups
CredentialEncrypted in database? Encrypted at rest, never logged

Always use Credential type for any username/password pair. This protects against:

  • Database exports exposing secrets
  • Orchestrator admins seeing passwords
  • Audit log leakage

Robot-Specific Assets

You can set different values per robot:

Asset NameRobot 1Robot 2Robot 3
WorkingFolderC:\Bot1\WorkC:\Bot2\WorkC:\Bot3\Work
BrowserTypeChromeEdgeChrome

Each robot automatically gets its own value.


Triggers and Scheduling

Schedule Triggers

Run processes on a cron schedule:

ScheduleCron ExpressionUse Case
Every hour0 * * * *Continuous polling
Daily at 6 AM0 6 * * *Morning batch
Weekdays only0 8 * * 1-5Business hours
First of month0 0 1 * *Monthly reports

Queue Triggers

Automatically start robots when items appear:

Queue Trigger Configuration:
├── Queue: Invoice_Processing
├── Minimum items: 10 (start when 10+ items)
├── Maximum robots: 5 (never more than 5 Performers)
├── Jobs per robot: 1 (one active job per robot)
└── Target folder: Production

This creates elastic scaling:

  • Queue has 0 items → 0 robots running
  • Queue has 50 items → 5 robots running (max)
  • Queue empties → robots stop automatically

Event Triggers

Start based on external events:

  • Email arrives in specific folder
  • File appears in watched directory
  • API webhook fires
  • Database record inserted

Monitoring and Analytics

Real-Time Dashboard

Orchestrator provides:

MetricWhat It Shows
Active JobsCurrently running processes
Queue ThroughputItems processed per hour
Success Rate% of items succeeding
Average Processing TimeHow long per item
Robot Utilization% of time robots are busy
Pending ItemsWork waiting in queue

SLA Monitoring

Configure SLA rules:

SLA Configuration:
├── Target: 95% of items within SLA
├── Risk threshold: 85%
├── Alert channels: Email, Slack
└── Escalation: If below 80% for 1 hour

When items approach their deadline, dashboards turn yellow/red.

Audit Logs

Every action is tracked:

2024-01-15 09:00:00 | Queue item INV-001 created by Dispatcher
2024-01-15 09:00:05 | Queue item INV-001 claimed by Robot_002
2024-01-15 09:01:23 | Queue item INV-001 completed successfully
2024-01-15 09:01:25 | Queue item INV-002 claimed by Robot_002
2024-01-15 09:02:45 | Queue item INV-002 failed - Business Exception
2024-01-15 09:02:46 | Queue item INV-002 status set to Failed

Multi-Robot Patterns

Pattern 1: Horizontal Scaling

Multiple identical Performers:

graph TD
    %% 定義節點
    Q[Queue<br/>1000 items]:::queue
    
    %% 定義機器人
    R1[Robot 1<br/>200]:::robot
    R2[Robot 2<br/>200]:::robot
    R3[Robot 3<br/>200]:::robot
    R4[Robot 4<br/>200]:::robot
    R5[Robot 5<br/>200]:::robot

    %% 連線關係
    Q --> R1
    Q --> R2
    Q --> R3
    Q --> R4
    Q --> R5

    %% 樣式設定
    classDef queue fill:#f9a825,stroke:#333,stroke-width:2px,color:white;
    classDef robot fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;

All robots run the same Performer process. Work distributes automatically.

Pattern 2: Pipeline Processing

Sequential stages:

Source → [Stage 1 Queue] → [Stage 2 Queue] → [Stage 3 Queue] → Done
              →                   →                   →
         Extract Bot         Validate Bot        Load Bot

Each stage has its own queue and specialized robot.

Pattern 3: Priority Lanes

Separate queues for different priorities:

High Priority Queue (SLA: 1 hour)   → Dedicated Robot
Normal Priority Queue (SLA: 24 hours) → Shared Robot Pool
Low Priority Queue (SLA: 1 week)    → Off-hours Robot

Best Practices

Queue Design

  1. One item = One transaction: Don’t batch multiple operations into one item
  2. Include all data: Queue item should be self-contained, no external lookups
  3. Use meaningful references: Make debugging easier with readable IDs
  4. Set appropriate retry counts: 0 for business, 2-3 for system exceptions

Performer Design

  1. Idempotent processing: Running twice should not cause duplicates
  2. Quick failure: Fail fast, don’t waste queue slot on doomed items
  3. Clear status codes: Distinguish business vs system failures
  4. Stateless: Don’t rely on previous items; each is independent

Monitoring

  1. Alert on queue growth: If items increase faster than processing
  2. Alert on failure spikes: Sudden increase in exceptions
  3. Daily review: Check successful vs failed ratio
  4. Capacity planning: Track growth for scaling decisions

Common Mistakes

Mistake 1: Everything in One Queue Item

// BAD: 100 invoices in one item
{
  "invoices": [
    {"id": "INV-001", "amount": 500},
    {"id": "INV-002", "amount": 750},
    // ... 98 more ...
  ]
}

If this fails, you retry all 100. Instead:

// GOOD: One invoice per item
{"id": "INV-001", "amount": 500}  // Item 1
{"id": "INV-002", "amount": 750}  // Item 2
// ... 98 more items ...

Mistake 2: External Dependencies in Performer

' BAD: Performer reads from Excel
invoiceData = ReadExcel("Pending_Invoices.xlsx")

If the file changes mid-processing, you have inconsistent data.

' GOOD: All data comes from queue item
invoiceData = queueItem.SpecificContent

Mistake 3: Not Setting Output

After processing, always set meaningful output:

' BAD: No output
SetTransactionStatus("Successful")

' GOOD: Rich output for debugging
SetTransactionStatus("Successful", 
    output: $"Invoice {invoiceNumber} posted with transaction ID {sapTxId}")

Key Takeaways

  1. Queues enable parallelism through work distribution, not faster code.
  2. Dispatcher-Performer pattern separates data loading from processing.
  3. Assets secure credentials and enable environment-specific configuration.
  4. Queue triggers enable elastic scaling based on demand.
  5. Monitoring and SLAs turn automation into a managed service.
  6. One item = one transaction is the foundation of reliable scaling.

With Orchestrator, you’re not managing scripts—you’re managing infrastructure. That shift in mindset is what transforms RPA from a tactical tool to a strategic platform.