In a multi-state workflow, each state receives the previous state's output as input. If State A produces a value that only State Z needs, that value must pass through every intermediate state, even when none of them use it. This chaining adds complexity and makes workflows harder to maintain.
Global variables solve this problem. Store a value in any state and read it directly from any other state, bypassing the entire chain.
Quick reference
| Operation | Syntax | Example |
|---|---|---|
| Write | GlobalConstructor in a state definition | myVar.$: $Output.Body |
| Read | $Global.<key> expression | $Global.myVar |
| Max key length | 128 Bytes | -- |
| Max value size | 256 KiB | -- |
How it works
Global variables provide execution-level key-value storage. Any state can write data to this storage when it finishes, and any subsequent state can read that data directly without receiving it through the input chain.
Constructors
CloudFlow uses three constructors to manage data flow within and across states:
| Constructor | Purpose | When to use |
|---|---|---|
GlobalConstructor | Write values to global storage | Share data across non-adjacent states |
InputConstructor | Reshape incoming data for a state | Filter or restructure input before a state runs |
OutputConstructor | Reshape outgoing data from a state | Filter or restructure output before passing to the next state |
All three constructors can reference both $Context and $Global to extract information.
The following diagram shows how constructors interact within a state:
Key behaviors:
$Outputis the raw result of the Task call. For asynchronous callback tasks,$Outputcontains the callback result.When
GlobalConstructorruns, its output merges with the existing$Globalvalues:$Global = Merge($Global, GlobalConstructor($Context, $Global)).$Globalis accessible throughout the entire workflow execution.
Evaluation order
Constructors evaluate in a fixed order within each state. Understanding this order is critical because GlobalConstructor and OutputConstructor read different snapshots of $Output and $Global:
The Task runs and produces
$Output(the raw task result).GlobalConstructorevaluates, using$Output(the raw task result, not theOutputConstructorresult).OutputConstructorevaluates, using$Global(the value beforeGlobalConstructorupdates it).
Worked example:
A Task state returns $Output = {"status": "ok", "data": {"id": 42}}. The current global storage is $Global = {"previousId": 10}.
GlobalConstructor:
latestId.$: $Output.data.id # Writes 42 to $Global.latestId
OutputConstructor:
combined.$: $Global.previousId # Reads 10 (the value BEFORE GlobalConstructor ran)After this state completes:
$Global={"previousId": 10, "latestId": 42}(merged)The state output =
{"combined": 10}(used the pre-update$Globalvalue)
$Output in GlobalConstructor refers to the raw output of the Task state, not the result of OutputConstructor. Likewise, $Global in OutputConstructor refers to the value before GlobalConstructor updates it.
Write global variables
Use GlobalConstructor to write global variables. It runs at the end of each state execution, and its data structure is Map[String]Any.
The following example stores the header and body of a function response as separate global variables:
Type: StateMachine
Name: MyWorkFlow
SpecVersion: v1
StartAt: InvokeFunction
States:
- Type: Task
Name: InvokeFunction
Action: FC:InvokeFunction
TaskMode: RequestComplete
Parameters:
resourceArn: >-
acs:fc:cn-hangzhou:123456:functions/myFunction/LATEST
invocationType: Sync
body.$: $Input
GlobalConstructor:
InvokeFunctionResultHeader.$: $Output.Header # Store the response header
InvokeFunctionResultBody.$: $Output.Body # Store the response body
End: trueIn this definition:
InvokeFunctionResultHeader.$: $Output.Headerstores the function response header in theInvokeFunctionResultHeaderglobal variable.InvokeFunctionResultBody.$: $Output.Bodystores the function response body in theInvokeFunctionResultBodyglobal variable.
Read global variables
Use the $Global keyword to read global variables. Any expression that supports construction can access global storage through $Global.<key>.
The following example shows a two-state workflow where the first state writes a global variable and the second reads it:
Type: StateMachine
Name: MyWorkFlow
SpecVersion: v1
StartAt: InvokeFunction1
States:
- Type: Task
Name: InvokeFunction1
Action: FC:InvokeFunction
TaskMode: RequestComplete
Parameters:
invocationType: Sync
resourceArn: acs:fc:cn-hangzhou:123456:functions/myFunction/LATEST
GlobalConstructor:
InvokeFunctionPayload.$: $Output.Body # Store the response body for later use
Next: InvokeFunction
- Type: Task
Name: InvokeFunction
Action: FC:InvokeFunction
TaskMode: RequestComplete
Parameters:
resourceArn: acs:fc:cn-hangzhou:123456:functions/myFunction/LATEST
invocationType: Sync
body.$: $Global.InvokeFunctionPayload # Read the stored value as input
OutputConstructor:
demo.$: $Global # Output the entire global storage
End: trueIn this definition:
InvokeFunction1stores its response body in theInvokeFunctionPayloadglobal variable.InvokeFunctionreads$Global.InvokeFunctionPayloadand passes it as thebodyparameter to the function call.OutputConstructormaps the full$Globalcontents to thedemofield in the state output.
Verify global variable values by inspecting the execution output in the CloudFlow console:

Limitations
| Item | Maximum value |
|---|---|
| Variable key length | 128 Bytes |
| Variable value length | 256 KiB |
Context size (InputConstructor and OutputConstructor output when using $Global) | 64 KiB |
If these limits do not meet your needs, submit a ticket to request an increase.
When passing data through $Global, the output of both InputConstructor and OutputConstructor must stay within the 64 KiB context size limit.
Race conditions in parallel execution
Global variables are shared across all states in an execution. When parallel logic (Parallel or Map states) exists, concurrent writes can overwrite each other. Follow these guidelines:
| Scenario | Guidance |
|---|---|
| Parallel states | Use a unique key per branch. Each branch writes to its own key to avoid overwrites. |
| Map states | Do not write global variables. All iterations share the same GlobalConstructor definition, so they write to the same keys and overwrite each other. |
| Distributed child executions | A child execution in distributed mode cannot access the parent execution's global variables. They run at different Execution levels with separate global storage. |