Orkes logo image
Product
Platform
Orkes Platform thumbnail
Orkes Platform
Orkes Agentic Workflows
Orkes Conductor Vs Conductor OSS thumbnail
Orkes vs. Conductor OSS
Orkes Cloud
How Orkes Powers Boat Thumbnail
How Orkes Powers BOAT
Try enterprise Orkes Cloud for free
Enjoy a free 14-day trial with all enterprise features
Start for free
Capabilities
Microservices Workflow Orchestration icon
Microservices Workflow Orchestration
Enable faster development cycles, easier maintenance, and improved user experiences.
Realtime API Orchestration icon
Realtime API Orchestration
Enable faster development cycles, easier maintenance, and improved user experiences.
Event Driven Architecture icon
Event Driven Architecture
Create durable workflows that promote modularity, flexibility, and responsiveness.
Human Workflow Orchestration icon
Human Workflow Orchestration
Seamlessly insert humans in the loop of complex workflows.
Process orchestration icon
Process Orchestration
Visualize end-to-end business processes, connect people, processes and systems, and monitor performance to resolve issues in real-time
Use Cases
By Industry
Financial Services icon
Financial Services
Secure and comprehensive workflow orchestration for financial services
Media and Entertainment icon
Media and Entertainment
Enterprise grade workflow orchestration for your media pipelines
Telecommunications icon
Telecommunications
Future proof your workflow management with workflow orchestration
Healthcare icon
Healthcare
Revolutionize and expedite patient care with workflow orchestration for healthcare
Shipping and logistics icon
Shipping and Logistics
Reinforce your inventory management with durable execution and long running workflows
Software icon
Software
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean leo mauris, laoreet interdum sodales a, mollis nec enim.
Docs
Developers
Learn
Blog
Explore our blog for insights into the latest trends in workflow orchestration, real-world use cases, and updates on how our solutions are transforming industries.
Read blogs
Check out our latest blog:
Conductor CLI Guide: Register, Run, Retry, and Recover Durable Workflows Without Leaving Your Terminal šŸ’»
Customers
Discover how leading companies are using Orkes to accelerate development, streamline operations, and achieve remarkable results.
Read case studies
Our latest case study:
Twilio Case Study Thumbnail
Orkes Academy New!
Master workflow orchestration with hands-on labs, structured learning paths, and certification. Build production-ready workflows from fundamentals to Agentic AI.
Explore courses
Featured course:
Orkes Academy Thumbnail
Events icon
Events
Videos icons
Videos
In the news icon
In the News
Whitepapers icon
Whitepapers
About us icon
About Us
Pricing
Get a demo
Signup
Slack FaviconDiscourse Logo icon
Get a demo
Signup
Slack FaviconDiscourse Logo icon
Orkes logo image

Company

Platform
Careers
HIRING!
Partners
About Us
Legal Hub
Security

Product

Cloud
Platform
Support

Community

Docs
Blogs
Events

Use Cases

Microservices Workflow Orchestration
Realtime API Orchestration
Event Driven Architecture
Agentic Workflows
Human Workflow Orchestration
Process Orchestration

Compare

Orkes vsĀ Camunda
Orkes vsĀ BPMN
Orkes vsĀ LangChain
Orkes vsĀ Temporal
Twitter or X Socials linkLinkedIn Socials linkYouTube Socials linkSlack Socials linkGithub Socials linkFacebook iconInstagram iconTik Tok icon
Ā© 2026 Orkes. All Rights Reserved.
Back to Blogs

Table of Contents

Share on:Share on LinkedInShare on FacebookShare on Twitter
Worker Code Illustration

Get Started for Free with Dev Edition

Signup
Back to Blogs
PRODUCT

Reduce, Reuse, Recycle - Optimizing workflows in Conductor with Operators

Orkes Team
Developer Relations
Last updated: August 5, 2022
August 5, 2022
10 min read

Related Blogs

Fail Fast, Recover Smart: Timeouts, Retries, and Recovery in Orkes Conductor

May 12, 2025

Fail Fast, Recover Smart: Timeouts, Retries, and Recovery in Orkes Conductor

Task-Level Resilience in Orkes Conductor: Timeouts and Retries in Action

May 12, 2025

Task-Level Resilience in Orkes Conductor: Timeouts and Retries in Action

Workflow-Level Resilience in Orkes Conductor: Timeouts and Failure Workflows

May 12, 2025

Workflow-Level Resilience in Orkes Conductor: Timeouts and Failure Workflows

Ready to Build Something Amazing?

Join thousands of developers building the future with Orkes.

Start for free

The idea of reduce, reuse and recycle is reverberated around the world as a conservation technique - if we use fewer materials, and reuse or recycle what we already are using, we lower our burden on the earth and its ecosystem.

As developers, we love the idea of reducing, reusing and recycling code. Just look at the prevalent use of StackOverflow, and the huge use of open source and libraries - if someone else has built it well - why not recycle the code and reuse it?

In this post, we'll apply the 3 R's of reduce, reuse and recycling to the topic of Conductor workflows - helping us create workflows that are compact, and easier to follow, and complete the desired task. Through our simplification of the workflow we'll also move from a workflow that is hardcoded to one specific task to a workflow that is more easily adapted to other similar uses - making the workflow more useful to the organization.

An analogy

Netflix Conductor is a workflow orchestration engine. But for our workflow, let's shift gears to a different type of orchestration and conductor.

In the classical period (think Mozart and Haydn), the 3rd movement of symphonies were mostly written in the style of a "minuet and trio." If you looked at the musical score (the workflow in this loose analogy), the 3rd movement appears to be short... until you look at the details.

A minuet is a dance, and so the musical phrases repeat themselves a lot. Rather than write out the music over and over, the repeat sign is used:

a simple fork diagram

The big thick line with two dots in the middle of the staff denote the region to be repeated. When you hit the "right repeat" the musicians all know to go back to the "left repeat". Just like coders use brackets to denote a function, the repeat sign is part of musical nomenclature. Repeats can also be flexible - in this example, the 2nd playback is slightly different at the ending.

This of course saved paper, ink, and the wrists of the music copyists.

In a minuet and trio, there are four total musical phrases. The minuet has 2 sections (A & B), and the trio has 2 sections (C & D). Each section is repeated after being played. (4 sections repeated - that's 8 sections total.) But there's more! After the trio is played, the dance has a "da capo." If you know Italian, this means "back to the top". The Minuet is played again - but this time without repeats. So we end up with 10 sections to the movement:

  • minuet A A B B
  • trio C C D D
  • minuet (Da Capo) A B

Let's build a workflow where Netflix Conductor simulates a orchestral conductor performing a minuet and trio.

The Workflow

Reusing tasks

If you were attempting to build a minuet_and_trio workflow in Conductor, you can define 4 tasks and reuse them over and over:

  • minuet_a
  • minuet_b
  • trio_c
  • trio_d

Reusing tasks is a common use case in Conductor. As long as the taskReferenceName is different, you can reuse tasks as often as you desire.

Knowing this, you might create a minuet_trio workflow with the 4 tasks, but with 10 taskReferenceNames:

minuet treio - but not efficiently

Even with re-using tasks, we can make this workflow smaller - I'm exhausted scrolling past this workflow. Further, this workflow is pretty much a "one hit wonder" - it is hardcoded for the 4 tasks and that's it.

Recycling tasks

DO/WHILE loop

Another way that we can reduce the amount of code in our workflow is to place tasks that repeat into a loop.

In music, the repeat notation keeps us from writing out the same music more than once. In this case, we'll use a DO_WHILE loop to repeat each section.

For example a workflow describing just the minuet section could look like this:

using loops to simulate a repeat

Here is the JSON that defines a minuet workflow:

json
{
  "updateTime": 1658836852189,
  "name": "minuet",
  "description": "Edit or extend this sample workflow. Set the workflow name to get started",
  "version": 1,
  "tasks": [
    {
      "name": "minuet_a_loop",
      "taskReferenceName": "minuet_a_loop",
      "inputParameters": {
        // highlight-next-line
        "repeats": "${workflow.input.repeats}"
      },
      "type": "DO_WHILE",
      "decisionCases": {},
      "defaultCase": [],
      "forkTasks": [],
      "startDelay": 0,
      "joinOn": [],
      "optional": false,
      "defaultExclusiveJoinTask": [],
      "asyncComplete": false,
      // highlight-next-line
      "loopCondition": "$.minuet_a_loop['iteration'] < $.repeats",
      "loopOver": [
        {
          "name": "minuet_a",
          "taskReferenceName": "minuet_a1",
          "inputParameters": {},
          "type": "SIMPLE",
          "decisionCases": {},
          "defaultCase": [],
          "forkTasks": [],
          "startDelay": 0,
          "joinOn": [],
          "optional": false,
          "defaultExclusiveJoinTask": [],
          "asyncComplete": false,
          "loopOver": []
        }
      ]
    },
    {
      "name": "minuet_b_loop",
      "taskReferenceName": "minuet_b_loop",
      "inputParameters": {
        // highlight-next-line
        "repeats": "${workflow.input.repeats}"
      },
      "type": "DO_WHILE",
      "decisionCases": {},
      "defaultCase": [],
      "forkTasks": [],
      "startDelay": 0,
      "joinOn": [],
      "optional": false,
      "defaultExclusiveJoinTask": [],
      "asyncComplete": false,
      // highlight-next-line
      "loopCondition": "$.minuet_b_loop['iteration']<$.repeats",
      "loopOver": [
        {
          "name": "minuet_b",
          "taskReferenceName": "minuet_b1",
          "inputParameters": {},
          "type": "SIMPLE",
          "decisionCases": {},
          "defaultCase": [],
          "forkTasks": [],
          "startDelay": 0,
          "joinOn": [],
          "optional": false,
          "defaultExclusiveJoinTask": [],
          "asyncComplete": false,
          "loopOver": []
        }
      ]
    }
  ],
  "inputParameters": [
    // highlight-next-line
    "repeats"
  ],
  "outputParameters": {
    "minueta_output": "${minuet_a_loop.output}",
    "minuetb_output": "${minuet_b_loop.output}"
  },
  "schemaVersion": 2,
  "restartable": true,
  "workflowStatusListenerEnabled": false,
  "ownerEmail": "doug.sillars@orkes.io",
  "timeoutPolicy": "ALERT_ONLY",
  "timeoutSeconds": 0,
  "variables": {},
  "inputTemplate": {}
}

A few items to note:

  • The two loops have an inputParameter called repeats. The looping definition is set to continue as long as the counter is less than the number of repeats:
javascript
"$.minuet_a_loop['iteration'] < $.repeats",
  • This is a complete workflow - not a part of the bigger minuet and trio workflow. We can call this inside our minute_trio workflow as a SUBWORKFLOW.

Subworkflow

Subworkflows are a GREAT way to recycle your code. Create a self contained subworkflow and then call it any time that it is needed.

If we go back to our minuet and trio analogy, the playback is

  1. minuet A
  2. minuet A
  3. minuet B
  4. minuet B
  5. trio C
  6. trio C
  7. trio D
  8. trio D
  9. minuet A
  10. minuet B

the minuet subworkflow above can replace lines 1-4 by setting the repeats input to 2. This will cause both minuet A and B to repeat twice: AA BB.

Additionally, if we set repeats to 1, we can also call this subworkflow to replace lines 9 and 10 (AB).

If we imagine creating a similar workflow for the Trio section (to play lines 5-8 CCDD), our new minuet_trio workflow could look like this:

minuet trio workflow with subworkflows

Let's just imagine creating this trio SUBWORKFLOW, because there is one more reduce, reuse and recycle trick up our sleeve: the Dynamic task.

DYNAMIC Task

The DYNAMIC task is a placeholder that will run whatever task it it given at runtime.

So, rather than having 2 subworkflows, one for the minuet and one for the trio - we can have just one subworkflow.

The DO/WHILE with the repeats variable are the same, but inside the loops, we put in a DYNAMIC task. The DYNAMIC task calls the tasks that are sent as input to the SUBWORKFLOW workflow.input.firstPhrase and then workflow.input.secondPhrase.

json
{
  "updateTime": 1659113580244,
  "name": "dynamic_minuet",
  "description": "Edit or extend this sample workflow. Set the workflow name to get started",
  "version": 1,
  "tasks": [
    {
      "name": "minuet_a_loop",
      "taskReferenceName": "minuet_a_loop_ref",
      "inputParameters": {
        "repeats": "${workflow.input.repeats}"
      },
      "type": "DO_WHILE",
      "decisionCases": {},
      "defaultCase": [],
      "forkTasks": [],
      "startDelay": 0,
      "joinOn": [],
      "optional": false,
      "defaultExclusiveJoinTask": [],
      "asyncComplete": false,
      "loopCondition": "if ($.minuet_a_loop_ref['iteration'] < $.repeats) {true;} else {false;}",
      "loopOver": [
        {
          "name": "musica",
          "taskReferenceName": "muaica_ref",
          "inputParameters": {
            // highlight-next-line
            "taskToExecute": "${workflow.input.firstPhrase}"
          },
          "type": "DYNAMIC",
          "dynamicTaskNameParam": "taskToExecute",
          "decisionCases": {},
          "defaultCase": [],
          "forkTasks": [],
          "startDelay": 0,
          "joinOn": [],
          "optional": false,
          "defaultExclusiveJoinTask": [],
          "asyncComplete": false,
          "loopOver": []
        }
      ]
    },
    {
      "name": "minuet_b_loop",
      "taskReferenceName": "minuet_b_loop_ref",
      "inputParameters": {
        "repeats": "${workflow.input.repeats}"
      },
      "type": "DO_WHILE",
      "decisionCases": {},
      "defaultCase": [],
      "forkTasks": [],
      "startDelay": 0,
      "joinOn": [],
      "optional": false,
      "defaultExclusiveJoinTask": [],
      "asyncComplete": false,
      "loopCondition": "$.minuet_b_loop_ref['iteration']< $.repeats",
      "loopOver": [
        {
          "name": "musicb",
          "taskReferenceName": "musicb_ref",
          "inputParameters": {
            // highlight-next-line
            "taskToExecute": "${workflow.input.secondPhrase}"
          },
          "type": "DYNAMIC",
          "dynamicTaskNameParam": "taskToExecute",
          "decisionCases": {},
          "defaultCase": [],
          "forkTasks": [],
          "startDelay": 0,
          "joinOn": [],
          "optional": false,
          "defaultExclusiveJoinTask": [],
          "asyncComplete": false,
          "loopOver": []
        }
      ]
    }
  ],
  "inputParameters": [],
  "outputParameters": {
    "loopa_output": "${minuet_a_loop_ref.output}",
    "loopb_output": "${minuet_b_loop_ref.output}"
  },
  "schemaVersion": 2,
  "restartable": true,
  "workflowStatusListenerEnabled": false,
  "ownerEmail": "doug.sillars@orkes.io",
  "timeoutPolicy": "ALERT_ONLY",
  "timeoutSeconds": 0,
  "variables": {},
  "inputTemplate": {}
}

The only difference is that instead of directly calling the first and second musical phrases - it can be called via a variable.

We can now use this subworkflow to call the beginning of the minuet:

json
{
    "firstPhrase":"minuet_a",
    "secondPhrase":"minuet_b",
    "repeats:2
}

Or the trio:

json
{
    "firstPhrase":"trio_c",
    "secondPhrase":"trio_d",
    "repeats:2
}

We can also call the da capo:

json
{
    "firstPhrase":"minuet_a",
    "secondPhrase":"minuet_b",
    "repeats:1
}

This one SUBWORKFLOW with DYNAMIC tasks allows us to configure a lot more of the workflow at runtime!

One more DO/WHILE

Now that our subworkflow has been optimized to play any part of the minuet/trio, we can simplify the entire workflow to play ANY minuet and trio, assuming that we have the tasks available.

Imagine this input:

json
{
  "phraseList": [
    {
      "firstPhrase": "minuet_a",
      "secondPhrase": "minuet_b",
      "repeats": 2
    },
    {
      "firstPhrase": "trio_c",
      "secondPhrase": "trio_d",
      "repeats": 2
    },
    {
      "firstPhrase": "minuet_a",
      "secondPhrase": "minuet_b",
      "repeats": 1
    }
  ]
}

This is now generalized for any minuet_trio song that might exist. Just supply the tasks and number of repeats, and the DO/WHILE loop can run the subworkflows for us:

In the DO/WHILE below, we have hard coded the iterations to 3 - to allow for a minuet section, a trio section and the Da Capo at the end:

minuet trio workflow with subworkflows

Why the Inline task? The inline task is extracting the JSON for each subworkflow from the input JSON array. Also note that the DO/WHILE counter starts at one, and the JSON array counter starts at zero, so we decrease the counter by one to extract the correct data from the JSON array.

Conclusion

By using loops, subworkflows and dynamic tasks, we have taken what was initially a workflow hardcoded for one minuet_trio and abstracted it so that it could be used for any minuet and trio, as long as the tasks are available to play the different musical phrases.

Assuming the tasks are available, this workflow could play the 3rd movement from Haydn's Surprise Symphony, or Mozart's Haffner Symphony by inputting the musical phrases and the standard repetitions.

Now for the fun sentence of the blog post that I have been waiting to write: We've built orchestration inside Netflix Conductor so that it is the conductor of a musical orchestration.

Do you want to try this yourself? The workflow is available on the Orkes Developer Edition, and there are 4 workers polling: minuet_a, minuet_b, trio_c and trio_d.