The aws:sfn/stateMachine:StateMachine resource, part of the Pulumi AWS provider, defines a Step Functions state machine: its workflow definition, execution type, and runtime configuration. This guide focuses on three capabilities: Standard vs Express workflow types, CloudWatch Logs integration, and customer-managed encryption.
State machines require IAM execution roles with Step Functions trust policies and reference Lambda functions or other AWS services in their workflow definitions. The examples are intentionally small. Combine them with your own IAM roles, Lambda functions, and observability infrastructure.
Define a Standard workflow with Lambda tasks
Most deployments start with a Standard workflow that orchestrates Lambda functions or other AWS services, providing exactly-once execution for workflows that can run up to one year.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// ...
const sfnStateMachine = new aws.sfn.StateMachine("sfn_state_machine", {
name: "my-state-machine",
roleArn: iamForSfn.arn,
definition: `{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
`,
});
import pulumi
import pulumi_aws as aws
# ...
sfn_state_machine = aws.sfn.StateMachine("sfn_state_machine",
name="my-state-machine",
role_arn=iam_for_sfn["arn"],
definition=f"""{{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {{
\"HelloWorld\": {{
\"Type\": \"Task\",
\"Resource\": \"{lambda_["arn"]}\",
\"End\": true
}}
}}
}}
""")
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sfn"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// ...
_, err := sfn.NewStateMachine(ctx, "sfn_state_machine", &sfn.StateMachineArgs{
Name: pulumi.String("my-state-machine"),
RoleArn: pulumi.Any(iamForSfn.Arn),
Definition: pulumi.Sprintf(`{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%v\",
\"End\": true
}
}
}
`, lambda.Arn),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// ...
var sfnStateMachine = new Aws.Sfn.StateMachine("sfn_state_machine", new()
{
Name = "my-state-machine",
RoleArn = iamForSfn.Arn,
Definition = @$"{{
\""Comment\"": \""A Hello World example of the Amazon States Language using an AWS Lambda Function\"",
\""StartAt\"": \""HelloWorld\"",
\""States\"": {{
\""HelloWorld\"": {{
\""Type\"": \""Task\"",
\""Resource\"": \""{lambda.Arn}\"",
\""End\"": true
}}
}}
}}
",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sfn.StateMachine;
import com.pulumi.aws.sfn.StateMachineArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// ...
var sfnStateMachine = new StateMachine("sfnStateMachine", StateMachineArgs.builder()
.name("my-state-machine")
.roleArn(iamForSfn.arn())
.definition("""
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%s\",
\"End\": true
}
}
}
", lambda.arn()))
.build());
}
}
resources:
# ...
sfnStateMachine:
type: aws:sfn:StateMachine
name: sfn_state_machine
properties:
name: my-state-machine
roleArn: ${iamForSfn.arn}
definition: |
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
The definition property contains the workflow logic in Amazon States Language, a JSON-based language that defines states and transitions. The roleArn grants the state machine permissions to invoke Lambda functions and other AWS services. Standard workflows (the default type) provide exactly-once execution semantics and full execution history.
Run high-throughput Express workflows
Express workflows handle high-volume event processing where at-least-once execution is acceptable, running for up to five minutes at lower cost than Standard workflows.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// ...
const sfnStateMachine = new aws.sfn.StateMachine("sfn_state_machine", {
name: "my-state-machine",
roleArn: iamForSfn.arn,
type: "EXPRESS",
definition: `{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
`,
});
import pulumi
import pulumi_aws as aws
# ...
sfn_state_machine = aws.sfn.StateMachine("sfn_state_machine",
name="my-state-machine",
role_arn=iam_for_sfn["arn"],
type="EXPRESS",
definition=f"""{{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {{
\"HelloWorld\": {{
\"Type\": \"Task\",
\"Resource\": \"{lambda_["arn"]}\",
\"End\": true
}}
}}
}}
""")
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sfn"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// ...
_, err := sfn.NewStateMachine(ctx, "sfn_state_machine", &sfn.StateMachineArgs{
Name: pulumi.String("my-state-machine"),
RoleArn: pulumi.Any(iamForSfn.Arn),
Type: pulumi.String("EXPRESS"),
Definition: pulumi.Sprintf(`{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%v\",
\"End\": true
}
}
}
`, lambda.Arn),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// ...
var sfnStateMachine = new Aws.Sfn.StateMachine("sfn_state_machine", new()
{
Name = "my-state-machine",
RoleArn = iamForSfn.Arn,
Type = "EXPRESS",
Definition = @$"{{
\""Comment\"": \""A Hello World example of the Amazon States Language using an AWS Lambda Function\"",
\""StartAt\"": \""HelloWorld\"",
\""States\"": {{
\""HelloWorld\"": {{
\""Type\"": \""Task\"",
\""Resource\"": \""{lambda.Arn}\"",
\""End\"": true
}}
}}
}}
",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sfn.StateMachine;
import com.pulumi.aws.sfn.StateMachineArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// ...
var sfnStateMachine = new StateMachine("sfnStateMachine", StateMachineArgs.builder()
.name("my-state-machine")
.roleArn(iamForSfn.arn())
.type("EXPRESS")
.definition("""
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%s\",
\"End\": true
}
}
}
", lambda.arn()))
.build());
}
}
resources:
# ...
sfnStateMachine:
type: aws:sfn:StateMachine
name: sfn_state_machine
properties:
name: my-state-machine
roleArn: ${iamForSfn.arn}
type: EXPRESS
definition: |
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
Setting type to EXPRESS changes the execution model: Express workflows prioritize throughput and cost over execution guarantees. They’re ideal for event processing pipelines where occasional duplicate executions are acceptable.
Send execution history to CloudWatch Logs
Production workflows need visibility into execution history for debugging and compliance. Step Functions sends execution events to CloudWatch Logs with configurable detail levels.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// ...
const sfnStateMachine = new aws.sfn.StateMachine("sfn_state_machine", {
name: "my-state-machine",
roleArn: iamForSfn.arn,
definition: `{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
`,
loggingConfiguration: {
logDestination: `${logGroupForSfn.arn}:*`,
includeExecutionData: true,
level: "ERROR",
},
});
import pulumi
import pulumi_aws as aws
# ...
sfn_state_machine = aws.sfn.StateMachine("sfn_state_machine",
name="my-state-machine",
role_arn=iam_for_sfn["arn"],
definition=f"""{{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {{
\"HelloWorld\": {{
\"Type\": \"Task\",
\"Resource\": \"{lambda_["arn"]}\",
\"End\": true
}}
}}
}}
""",
logging_configuration={
"log_destination": f"{log_group_for_sfn['arn']}:*",
"include_execution_data": True,
"level": "ERROR",
})
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sfn"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// ...
_, err := sfn.NewStateMachine(ctx, "sfn_state_machine", &sfn.StateMachineArgs{
Name: pulumi.String("my-state-machine"),
RoleArn: pulumi.Any(iamForSfn.Arn),
Definition: pulumi.Sprintf(`{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%v\",
\"End\": true
}
}
}
`, lambda.Arn),
LoggingConfiguration: &sfn.StateMachineLoggingConfigurationArgs{
LogDestination: pulumi.Sprintf("%v:*", logGroupForSfn.Arn),
IncludeExecutionData: pulumi.Bool(true),
Level: pulumi.String("ERROR"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// ...
var sfnStateMachine = new Aws.Sfn.StateMachine("sfn_state_machine", new()
{
Name = "my-state-machine",
RoleArn = iamForSfn.Arn,
Definition = @$"{{
\""Comment\"": \""A Hello World example of the Amazon States Language using an AWS Lambda Function\"",
\""StartAt\"": \""HelloWorld\"",
\""States\"": {{
\""HelloWorld\"": {{
\""Type\"": \""Task\"",
\""Resource\"": \""{lambda.Arn}\"",
\""End\"": true
}}
}}
}}
",
LoggingConfiguration = new Aws.Sfn.Inputs.StateMachineLoggingConfigurationArgs
{
LogDestination = $"{logGroupForSfn.Arn}:*",
IncludeExecutionData = true,
Level = "ERROR",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sfn.StateMachine;
import com.pulumi.aws.sfn.StateMachineArgs;
import com.pulumi.aws.sfn.inputs.StateMachineLoggingConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// ...
var sfnStateMachine = new StateMachine("sfnStateMachine", StateMachineArgs.builder()
.name("my-state-machine")
.roleArn(iamForSfn.arn())
.definition("""
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%s\",
\"End\": true
}
}
}
", lambda.arn()))
.loggingConfiguration(StateMachineLoggingConfigurationArgs.builder()
.logDestination(String.format("%s:*", logGroupForSfn.arn()))
.includeExecutionData(true)
.level("ERROR")
.build())
.build());
}
}
resources:
# ...
sfnStateMachine:
type: aws:sfn:StateMachine
name: sfn_state_machine
properties:
name: my-state-machine
roleArn: ${iamForSfn.arn}
definition: |
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
loggingConfiguration:
logDestination: ${logGroupForSfn.arn}:*
includeExecutionData: true
level: ERROR
The loggingConfiguration property controls what gets logged. The logDestination points to a CloudWatch Log Group (note the :* suffix required by Step Functions). Setting includeExecutionData to true includes input and output data in logs; level controls verbosity (ERROR, ALL, or OFF).
Encrypt state machine data with customer-managed keys
Compliance requirements often mandate encryption using customer-managed KMS keys rather than AWS-managed keys.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// ...
const sfnStateMachine = new aws.sfn.StateMachine("sfn_state_machine", {
name: "my-state-machine",
roleArn: iamForSfn.arn,
definition: `{
\"Comment\": \"A Hello World example of the Amazon States Language using an [AWS Lambda Function](/guides/how-to/aws-lambda-function/)\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
`,
encryptionConfiguration: {
kmsKeyId: kmsKeyForSfn.arn,
type: "CUSTOMER_MANAGED_KMS_KEY",
kmsDataKeyReusePeriodSeconds: 900,
},
});
import pulumi
import pulumi_aws as aws
# ...
sfn_state_machine = aws.sfn.StateMachine("sfn_state_machine",
name="my-state-machine",
role_arn=iam_for_sfn["arn"],
definition=f"""{{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {{
\"HelloWorld\": {{
\"Type\": \"Task\",
\"Resource\": \"{lambda_["arn"]}\",
\"End\": true
}}
}}
}}
""",
encryption_configuration={
"kms_key_id": kms_key_for_sfn["arn"],
"type": "CUSTOMER_MANAGED_KMS_KEY",
"kms_data_key_reuse_period_seconds": 900,
})
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sfn"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// ...
_, err := sfn.NewStateMachine(ctx, "sfn_state_machine", &sfn.StateMachineArgs{
Name: pulumi.String("my-state-machine"),
RoleArn: pulumi.Any(iamForSfn.Arn),
Definition: pulumi.Sprintf(`{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS [Lambda Function](/guides/how-to/aws-lambda-function/)\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%v\",
\"End\": true
}
}
}
`, lambda.Arn),
EncryptionConfiguration: &sfn.StateMachineEncryptionConfigurationArgs{
KmsKeyId: pulumi.Any(kmsKeyForSfn.Arn),
Type: pulumi.String("CUSTOMER_MANAGED_KMS_KEY"),
KmsDataKeyReusePeriodSeconds: pulumi.Int(900),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// ...
var sfnStateMachine = new Aws.Sfn.StateMachine("sfn_state_machine", new()
{
Name = "my-state-machine",
RoleArn = iamForSfn.Arn,
Definition = @$"{{
\""Comment\"": \""A Hello World example of the Amazon States Language using an AWS Lambda Function\"",
\""StartAt\"": \""HelloWorld\"",
\""States\"": {{
\""HelloWorld\"": {{
\""Type\"": \""Task\"",
\""Resource\"": \""{lambda.Arn}\"",
\""End\"": true
}}
}}
}}
",
EncryptionConfiguration = new Aws.Sfn.Inputs.StateMachineEncryptionConfigurationArgs
{
KmsKeyId = kmsKeyForSfn.Arn,
Type = "CUSTOMER_MANAGED_KMS_KEY",
KmsDataKeyReusePeriodSeconds = 900,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sfn.StateMachine;
import com.pulumi.aws.sfn.StateMachineArgs;
import com.pulumi.aws.sfn.inputs.StateMachineEncryptionConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// ...
var sfnStateMachine = new StateMachine("sfnStateMachine", StateMachineArgs.builder()
.name("my-state-machine")
.roleArn(iamForSfn.arn())
.definition("""
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"%s\",
\"End\": true
}
}
}
", lambda.arn()))
.encryptionConfiguration(StateMachineEncryptionConfigurationArgs.builder()
.kmsKeyId(kmsKeyForSfn.arn())
.type("CUSTOMER_MANAGED_KMS_KEY")
.kmsDataKeyReusePeriodSeconds(900)
.build())
.build());
}
}
resources:
# ...
sfnStateMachine:
type: aws:sfn:StateMachine
name: sfn_state_machine
properties:
name: my-state-machine
roleArn: ${iamForSfn.arn}
definition: |
{
\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",
\"StartAt\": \"HelloWorld\",
\"States\": {
\"HelloWorld\": {
\"Type\": \"Task\",
\"Resource\": \"${lambda.arn}\",
\"End\": true
}
}
}
encryptionConfiguration:
kmsKeyId: ${kmsKeyForSfn.arn}
type: CUSTOMER_MANAGED_KMS_KEY
kmsDataKeyReusePeriodSeconds: 900
The encryptionConfiguration property enables customer-managed encryption. Set type to CUSTOMER_MANAGED_KMS_KEY and provide a kmsKeyId. The kmsDataKeyReusePeriodSeconds property controls how often Step Functions requests new data keys (between 60 and 900 seconds).
Beyond these examples
These snippets focus on specific state machine features: Standard and Express workflow types, CloudWatch Logs integration, and customer-managed encryption. They’re intentionally minimal rather than full workflow applications.
The examples reference pre-existing infrastructure such as IAM execution roles with Step Functions trust policies, Lambda functions referenced in state machine definitions, CloudWatch Log Groups, and KMS keys. They focus on configuring the state machine rather than provisioning everything around it.
To keep things focused, common state machine patterns are omitted, including:
- X-Ray distributed tracing (tracingConfiguration)
- State machine versioning (publish property)
- Tags for organization and cost tracking
- Complex state machine definitions (parallel states, error handling, retries)
These omissions are intentional: the goal is to illustrate how each state machine feature is wired, not provide drop-in workflow modules. See the Step Functions StateMachine resource reference for all available configuration options.
Let's create AWS Step Functions State Machines
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Workflow Types & Immutability
type after creation; to switch types, you must create a new state machine.name, namePrefix, and type properties are immutable. Changing any of these requires creating a new state machine.Naming & Identification
0-9, A-Z, a-z, -, and _. Other characters are not allowed.name to specify an exact name, or namePrefix to generate a unique name with your specified prefix. You cannot use both properties together; they conflict.Logging & Monitoring
loggingConfiguration with logDestination (CloudWatch log group ARN with :* suffix), includeExecutionData, and level (ERROR, ALL, FATAL, or OFF). Logging is available for both STANDARD and EXPRESS workflows.tracingConfiguration property to enable AWS X-Ray tracing for your state machine executions.Security & Encryption
encryptionConfiguration with kmsKeyId (your KMS key ARN), type set to CUSTOMER_MANAGED_KMS_KEY, and optionally kmsDataKeyReusePeriodSeconds (e.g., 900 seconds).Versioning
publish to true. This publishes a version of the state machine when it’s created. The default is false.Using a different cloud?
Explore integration guides for other cloud providers: