Process variables in synchronous execution

Hi Team,

I’m using Flowable 7.1 embedded with PostgreSQL. We have a requirement for ultra-low execution time, so our BPMN processes include only synchronous steps (async = false).

As runtimeService.startProcessInstanceByKey waits for all synchronous steps to complete, I intend to retrieve process variables directly from the ProcessInstance object, avoiding any history table queries for performance reasons.

However, I came across a note that if the BPMN includes scripts or sub-processes, not all variables may be available on the ProcessInstance. Could you confirm if this is true?

This is critical for our use case, and your clarification would be greatly appreciated.

Hey @dhatric,

Where have you seen this note?

The process variables retrieved through ProcessInstance after starting it should return all process instance variables. If you had some local variables or if you didn’t map the output variables from a Call Activity then you won’t see those. However, that’s entirely on you how you model your process.

e.g. if you used execution.setLocalVariable then you will not see that variable in the process variables. However, if you do execution.setVariable you should be able to see it.

Cheers,
Filip

1 Like

@filiphr Thanks for the quick clarification. I might have misunderstood the context in an earlier post on this forum.

Just to confirm my understanding:

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("helloProcess", variables);
return processInstance.getProcessVariables();

The above code will return all process variables from in-memory ProcessInstance object.

All the variables that are direct variables of the process instance. However, if you are using local variables, then it won’t return those.

e.g. if you have a sub process, and in this sub process you have a script task in which you do execution.setLocalVariable, then this variable will not be a process instance variable, but a local variable to the sub process.

Hope this clarifies your question.
Cheers,
Filip

@filiphr Understood. Thanks a ton.

@filiphr We’re facing challenges in achieving ultra-low latency (~50 milliseconds) for synchronous workflow execution under load. On closer inspection, I noticed that even a single workflow execution triggers several database queries, such as:

  • SELECT * FROM ACT_RU_EXECUTION WHERE PARENT_ID_ = ?
  • SELECT * FROM ACT_RU_EXECUTION WHERE PROC_INST_ID_ = ? AND PARENT_ID_ IS NOT NULL
  • SELECT * FROM ACT_RU_EXECUTION WHERE SUPER_EXEC_ = ? (executed twice)
  • SELECT * FROM ACT_RU_VARIABLE WHERE SUB_SCOPE_ID_ = ? AND SCOPE_TYPE_ IN (?, ?)

Are these queries necessary for synchronous flows, or is there a way to optimize or eliminate them to reduce latency?

Also, I was under the impression that in purely synchronous execution, the engine could bypass runtime tables and directly write to history tables (when history is enabled). Is that understanding incorrect?

Hey @dhatric,

When you say synchronous flows, do you mean flows that start a process instance and finish one in the same transaction?

From the 4 queries you shared, 3 might be needed or could be optimized further and need a bit more analysis.

For

We already found this one and we have optimized it on main Prevent unnecessary select execution by super execution id query · flowable/flowable-engine@502a54f · GitHub

That should indeed be the case. However, there might be some things that could be optimized further, by skipping the queries if they are not needed.

Can you perhaps share some of your flows where you are trying this so we can also try them out and look for optimizations we can add?

Cheers,
Filip

Below is the workflow definition. It has a single service task which appends hello to the input string.

<?xml version="1.0" encoding="UTF-8"?>
<definitions
        xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:flowable="http://flowable.org/bpmn"
        targetNamespace="Examples">

    <process id="helloProcess" name="Hello Process" isExecutable="true">

        <startEvent id="startEvent" name="Start"/>

        <serviceTask id="helloTask"
                     name="Hello Service Task"
                     flowable:delegateExpression="${helloServiceTask}" />

        <endEvent id="endEvent" name="End"/>

        <!-- Define the sequence flow -->
        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="helloTask"/>
        <sequenceFlow id="flow2" sourceRef="helloTask" targetRef="endEvent"/>

    </process>

</definitions>

When you say synchronous flows, do you mean flows that start a process instance and finish one in the same transaction? CORRECT

@filiphr appreciate your help here :slight_smile:

Thanks for sharing your BPMN XML. I do see that we can do some improvements in this area. I can’t promise when exactly though.

You can try setting the enableEagerExecutionTreeFetching flag to true to see if your performance improves.

Cheers,
Filip

@filiphr I tried that flag. It still does make all those calls.