Configure AWS Systems Manager Maintenance Window Tasks

The aws:ssm/maintenanceWindowTask:MaintenanceWindowTask resource, part of the Pulumi AWS provider, defines tasks that execute during SSM maintenance windows: automation documents, shell commands, Lambda functions, or Step Functions workflows. This guide focuses on three capabilities: automation document execution, shell command execution with output capture, and Lambda and Step Functions integration.

Maintenance window tasks belong to maintenance windows and target EC2 instances or window target groups. Run Command tasks may reference S3 buckets, IAM roles, and SNS topics for output and notifications. The examples are intentionally small. Combine them with your own maintenance windows, targets, and infrastructure.

Restart EC2 instances with automation documents

Maintenance windows often execute AWS-provided automation documents to perform common operations like restarting instances during scheduled periods.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.ssm.MaintenanceWindowTask("example", {
    maxConcurrency: "2",
    maxErrors: "1",
    priority: 1,
    taskArn: "AWS-RestartEC2Instance",
    taskType: "AUTOMATION",
    windowId: exampleAwsSsmMaintenanceWindow.id,
    targets: [{
        key: "InstanceIds",
        values: [exampleAwsInstance.id],
    }],
    taskInvocationParameters: {
        automationParameters: {
            documentVersion: "$LATEST",
            parameters: [{
                name: "InstanceId",
                values: [exampleAwsInstance.id],
            }],
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.ssm.MaintenanceWindowTask("example",
    max_concurrency="2",
    max_errors="1",
    priority=1,
    task_arn="AWS-RestartEC2Instance",
    task_type="AUTOMATION",
    window_id=example_aws_ssm_maintenance_window["id"],
    targets=[{
        "key": "InstanceIds",
        "values": [example_aws_instance["id"]],
    }],
    task_invocation_parameters={
        "automation_parameters": {
            "document_version": "$LATEST",
            "parameters": [{
                "name": "InstanceId",
                "values": [example_aws_instance["id"]],
            }],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ssm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ssm.NewMaintenanceWindowTask(ctx, "example", &ssm.MaintenanceWindowTaskArgs{
			MaxConcurrency: pulumi.String("2"),
			MaxErrors:      pulumi.String("1"),
			Priority:       pulumi.Int(1),
			TaskArn:        pulumi.String("AWS-RestartEC2Instance"),
			TaskType:       pulumi.String("AUTOMATION"),
			WindowId:       pulumi.Any(exampleAwsSsmMaintenanceWindow.Id),
			Targets: ssm.MaintenanceWindowTaskTargetArray{
				&ssm.MaintenanceWindowTaskTargetArgs{
					Key: pulumi.String("InstanceIds"),
					Values: pulumi.StringArray{
						exampleAwsInstance.Id,
					},
				},
			},
			TaskInvocationParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersArgs{
				AutomationParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersArgs{
					DocumentVersion: pulumi.String("$LATEST"),
					Parameters: ssm.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersParameterArray{
						&ssm.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersParameterArgs{
							Name: pulumi.String("InstanceId"),
							Values: pulumi.StringArray{
								exampleAwsInstance.Id,
							},
						},
					},
				},
			},
		})
		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 example = new Aws.Ssm.MaintenanceWindowTask("example", new()
    {
        MaxConcurrency = "2",
        MaxErrors = "1",
        Priority = 1,
        TaskArn = "AWS-RestartEC2Instance",
        TaskType = "AUTOMATION",
        WindowId = exampleAwsSsmMaintenanceWindow.Id,
        Targets = new[]
        {
            new Aws.Ssm.Inputs.MaintenanceWindowTaskTargetArgs
            {
                Key = "InstanceIds",
                Values = new[]
                {
                    exampleAwsInstance.Id,
                },
            },
        },
        TaskInvocationParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersArgs
        {
            AutomationParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersArgs
            {
                DocumentVersion = "$LATEST",
                Parameters = new[]
                {
                    new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersParameterArgs
                    {
                        Name = "InstanceId",
                        Values = new[]
                        {
                            exampleAwsInstance.Id,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ssm.MaintenanceWindowTask;
import com.pulumi.aws.ssm.MaintenanceWindowTaskArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTargetArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersAutomationParametersArgs;
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 example = new MaintenanceWindowTask("example", MaintenanceWindowTaskArgs.builder()
            .maxConcurrency("2")
            .maxErrors("1")
            .priority(1)
            .taskArn("AWS-RestartEC2Instance")
            .taskType("AUTOMATION")
            .windowId(exampleAwsSsmMaintenanceWindow.id())
            .targets(MaintenanceWindowTaskTargetArgs.builder()
                .key("InstanceIds")
                .values(exampleAwsInstance.id())
                .build())
            .taskInvocationParameters(MaintenanceWindowTaskTaskInvocationParametersArgs.builder()
                .automationParameters(MaintenanceWindowTaskTaskInvocationParametersAutomationParametersArgs.builder()
                    .documentVersion("$LATEST")
                    .parameters(MaintenanceWindowTaskTaskInvocationParametersAutomationParametersParameterArgs.builder()
                        .name("InstanceId")
                        .values(exampleAwsInstance.id())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ssm:MaintenanceWindowTask
    properties:
      maxConcurrency: 2
      maxErrors: 1
      priority: 1
      taskArn: AWS-RestartEC2Instance
      taskType: AUTOMATION
      windowId: ${exampleAwsSsmMaintenanceWindow.id}
      targets:
        - key: InstanceIds
          values:
            - ${exampleAwsInstance.id}
      taskInvocationParameters:
        automationParameters:
          documentVersion: $LATEST
          parameters:
            - name: InstanceId
              values:
                - ${exampleAwsInstance.id}

The taskArn property specifies the automation document to run (here, AWS-RestartEC2Instance). The taskType property must be set to AUTOMATION. The automationParameters block configures document-specific inputs, including the documentVersion and parameters array. The targets property specifies which instances to operate on using key-value pairs.

Execute shell scripts with output capture

Teams running custom scripts across fleets need to capture output and receive notifications about execution status.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.ssm.MaintenanceWindowTask("example", {
    maxConcurrency: "2",
    maxErrors: "1",
    priority: 1,
    taskArn: "AWS-RunShellScript",
    taskType: "RUN_COMMAND",
    windowId: exampleAwsSsmMaintenanceWindow.id,
    targets: [{
        key: "InstanceIds",
        values: [exampleAwsInstance.id],
    }],
    taskInvocationParameters: {
        runCommandParameters: {
            outputS3Bucket: exampleAwsS3Bucket.id,
            outputS3KeyPrefix: "output",
            serviceRoleArn: exampleAwsIamRole.arn,
            timeoutSeconds: 600,
            notificationConfig: {
                notificationArn: exampleAwsSnsTopic.arn,
                notificationEvents: ["All"],
                notificationType: "Command",
            },
            parameters: [{
                name: "commands",
                values: ["date"],
            }],
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.ssm.MaintenanceWindowTask("example",
    max_concurrency="2",
    max_errors="1",
    priority=1,
    task_arn="AWS-RunShellScript",
    task_type="RUN_COMMAND",
    window_id=example_aws_ssm_maintenance_window["id"],
    targets=[{
        "key": "InstanceIds",
        "values": [example_aws_instance["id"]],
    }],
    task_invocation_parameters={
        "run_command_parameters": {
            "output_s3_bucket": example_aws_s3_bucket["id"],
            "output_s3_key_prefix": "output",
            "service_role_arn": example_aws_iam_role["arn"],
            "timeout_seconds": 600,
            "notification_config": {
                "notification_arn": example_aws_sns_topic["arn"],
                "notification_events": ["All"],
                "notification_type": "Command",
            },
            "parameters": [{
                "name": "commands",
                "values": ["date"],
            }],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ssm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ssm.NewMaintenanceWindowTask(ctx, "example", &ssm.MaintenanceWindowTaskArgs{
			MaxConcurrency: pulumi.String("2"),
			MaxErrors:      pulumi.String("1"),
			Priority:       pulumi.Int(1),
			TaskArn:        pulumi.String("AWS-RunShellScript"),
			TaskType:       pulumi.String("RUN_COMMAND"),
			WindowId:       pulumi.Any(exampleAwsSsmMaintenanceWindow.Id),
			Targets: ssm.MaintenanceWindowTaskTargetArray{
				&ssm.MaintenanceWindowTaskTargetArgs{
					Key: pulumi.String("InstanceIds"),
					Values: pulumi.StringArray{
						exampleAwsInstance.Id,
					},
				},
			},
			TaskInvocationParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersArgs{
				RunCommandParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersArgs{
					OutputS3Bucket:    pulumi.Any(exampleAwsS3Bucket.Id),
					OutputS3KeyPrefix: pulumi.String("output"),
					ServiceRoleArn:    pulumi.Any(exampleAwsIamRole.Arn),
					TimeoutSeconds:    pulumi.Int(600),
					NotificationConfig: &ssm.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersNotificationConfigArgs{
						NotificationArn: pulumi.Any(exampleAwsSnsTopic.Arn),
						NotificationEvents: pulumi.StringArray{
							pulumi.String("All"),
						},
						NotificationType: pulumi.String("Command"),
					},
					Parameters: ssm.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersParameterArray{
						&ssm.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersParameterArgs{
							Name: pulumi.String("commands"),
							Values: pulumi.StringArray{
								pulumi.String("date"),
							},
						},
					},
				},
			},
		})
		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 example = new Aws.Ssm.MaintenanceWindowTask("example", new()
    {
        MaxConcurrency = "2",
        MaxErrors = "1",
        Priority = 1,
        TaskArn = "AWS-RunShellScript",
        TaskType = "RUN_COMMAND",
        WindowId = exampleAwsSsmMaintenanceWindow.Id,
        Targets = new[]
        {
            new Aws.Ssm.Inputs.MaintenanceWindowTaskTargetArgs
            {
                Key = "InstanceIds",
                Values = new[]
                {
                    exampleAwsInstance.Id,
                },
            },
        },
        TaskInvocationParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersArgs
        {
            RunCommandParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersArgs
            {
                OutputS3Bucket = exampleAwsS3Bucket.Id,
                OutputS3KeyPrefix = "output",
                ServiceRoleArn = exampleAwsIamRole.Arn,
                TimeoutSeconds = 600,
                NotificationConfig = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersNotificationConfigArgs
                {
                    NotificationArn = exampleAwsSnsTopic.Arn,
                    NotificationEvents = new[]
                    {
                        "All",
                    },
                    NotificationType = "Command",
                },
                Parameters = new[]
                {
                    new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersParameterArgs
                    {
                        Name = "commands",
                        Values = new[]
                        {
                            "date",
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ssm.MaintenanceWindowTask;
import com.pulumi.aws.ssm.MaintenanceWindowTaskArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTargetArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersNotificationConfigArgs;
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 example = new MaintenanceWindowTask("example", MaintenanceWindowTaskArgs.builder()
            .maxConcurrency("2")
            .maxErrors("1")
            .priority(1)
            .taskArn("AWS-RunShellScript")
            .taskType("RUN_COMMAND")
            .windowId(exampleAwsSsmMaintenanceWindow.id())
            .targets(MaintenanceWindowTaskTargetArgs.builder()
                .key("InstanceIds")
                .values(exampleAwsInstance.id())
                .build())
            .taskInvocationParameters(MaintenanceWindowTaskTaskInvocationParametersArgs.builder()
                .runCommandParameters(MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersArgs.builder()
                    .outputS3Bucket(exampleAwsS3Bucket.id())
                    .outputS3KeyPrefix("output")
                    .serviceRoleArn(exampleAwsIamRole.arn())
                    .timeoutSeconds(600)
                    .notificationConfig(MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersNotificationConfigArgs.builder()
                        .notificationArn(exampleAwsSnsTopic.arn())
                        .notificationEvents("All")
                        .notificationType("Command")
                        .build())
                    .parameters(MaintenanceWindowTaskTaskInvocationParametersRunCommandParametersParameterArgs.builder()
                        .name("commands")
                        .values("date")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ssm:MaintenanceWindowTask
    properties:
      maxConcurrency: 2
      maxErrors: 1
      priority: 1
      taskArn: AWS-RunShellScript
      taskType: RUN_COMMAND
      windowId: ${exampleAwsSsmMaintenanceWindow.id}
      targets:
        - key: InstanceIds
          values:
            - ${exampleAwsInstance.id}
      taskInvocationParameters:
        runCommandParameters:
          outputS3Bucket: ${exampleAwsS3Bucket.id}
          outputS3KeyPrefix: output
          serviceRoleArn: ${exampleAwsIamRole.arn}
          timeoutSeconds: 600
          notificationConfig:
            notificationArn: ${exampleAwsSnsTopic.arn}
            notificationEvents:
              - All
            notificationType: Command
          parameters:
            - name: commands
              values:
                - date

The taskType property is set to RUN_COMMAND for shell script execution. The runCommandParameters block configures output storage (outputS3Bucket, outputS3KeyPrefix), execution timeout (timeoutSeconds), and notifications (notificationConfig). The serviceRoleArn grants permissions to write to S3 and publish to SNS. The parameters array passes the actual commands to execute.

Invoke Lambda functions with custom payloads

Maintenance windows can trigger Lambda functions to perform custom logic, passing context and payload data to the function.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const example = new aws.ssm.MaintenanceWindowTask("example", {
    maxConcurrency: "2",
    maxErrors: "1",
    priority: 1,
    taskArn: exampleAwsLambdaFunction.arn,
    taskType: "LAMBDA",
    windowId: exampleAwsSsmMaintenanceWindow.id,
    targets: [{
        key: "InstanceIds",
        values: [exampleAwsInstance.id],
    }],
    taskInvocationParameters: {
        lambdaParameters: {
            clientContext: std.base64encode({
                input: "{\"key1\":\"value1\"}",
            }).then(invoke => invoke.result),
            payload: "{\"key1\":\"value1\"}",
        },
    },
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std

example = aws.ssm.MaintenanceWindowTask("example",
    max_concurrency="2",
    max_errors="1",
    priority=1,
    task_arn=example_aws_lambda_function["arn"],
    task_type="LAMBDA",
    window_id=example_aws_ssm_maintenance_window["id"],
    targets=[{
        "key": "InstanceIds",
        "values": [example_aws_instance["id"]],
    }],
    task_invocation_parameters={
        "lambda_parameters": {
            "client_context": std.base64encode(input="{\"key1\":\"value1\"}").result,
            "payload": "{\"key1\":\"value1\"}",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ssm"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		invokeBase64encode, err := std.Base64encode(ctx, &std.Base64encodeArgs{
			Input: "{\"key1\":\"value1\"}",
		}, nil)
		if err != nil {
			return err
		}
		_, err = ssm.NewMaintenanceWindowTask(ctx, "example", &ssm.MaintenanceWindowTaskArgs{
			MaxConcurrency: pulumi.String("2"),
			MaxErrors:      pulumi.String("1"),
			Priority:       pulumi.Int(1),
			TaskArn:        pulumi.Any(exampleAwsLambdaFunction.Arn),
			TaskType:       pulumi.String("LAMBDA"),
			WindowId:       pulumi.Any(exampleAwsSsmMaintenanceWindow.Id),
			Targets: ssm.MaintenanceWindowTaskTargetArray{
				&ssm.MaintenanceWindowTaskTargetArgs{
					Key: pulumi.String("InstanceIds"),
					Values: pulumi.StringArray{
						exampleAwsInstance.Id,
					},
				},
			},
			TaskInvocationParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersArgs{
				LambdaParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersLambdaParametersArgs{
					ClientContext: pulumi.String(invokeBase64encode.Result),
					Payload:       pulumi.String("{\"key1\":\"value1\"}"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Ssm.MaintenanceWindowTask("example", new()
    {
        MaxConcurrency = "2",
        MaxErrors = "1",
        Priority = 1,
        TaskArn = exampleAwsLambdaFunction.Arn,
        TaskType = "LAMBDA",
        WindowId = exampleAwsSsmMaintenanceWindow.Id,
        Targets = new[]
        {
            new Aws.Ssm.Inputs.MaintenanceWindowTaskTargetArgs
            {
                Key = "InstanceIds",
                Values = new[]
                {
                    exampleAwsInstance.Id,
                },
            },
        },
        TaskInvocationParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersArgs
        {
            LambdaParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersLambdaParametersArgs
            {
                ClientContext = Std.Base64encode.Invoke(new()
                {
                    Input = "{\"key1\":\"value1\"}",
                }).Apply(invoke => invoke.Result),
                Payload = "{\"key1\":\"value1\"}",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ssm.MaintenanceWindowTask;
import com.pulumi.aws.ssm.MaintenanceWindowTaskArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTargetArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersLambdaParametersArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Base64encodeArgs;
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 example = new MaintenanceWindowTask("example", MaintenanceWindowTaskArgs.builder()
            .maxConcurrency("2")
            .maxErrors("1")
            .priority(1)
            .taskArn(exampleAwsLambdaFunction.arn())
            .taskType("LAMBDA")
            .windowId(exampleAwsSsmMaintenanceWindow.id())
            .targets(MaintenanceWindowTaskTargetArgs.builder()
                .key("InstanceIds")
                .values(exampleAwsInstance.id())
                .build())
            .taskInvocationParameters(MaintenanceWindowTaskTaskInvocationParametersArgs.builder()
                .lambdaParameters(MaintenanceWindowTaskTaskInvocationParametersLambdaParametersArgs.builder()
                    .clientContext(StdFunctions.base64encode(Base64encodeArgs.builder()
                        .input("{\"key1\":\"value1\"}")
                        .build()).result())
                    .payload("{\"key1\":\"value1\"}")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ssm:MaintenanceWindowTask
    properties:
      maxConcurrency: 2
      maxErrors: 1
      priority: 1
      taskArn: ${exampleAwsLambdaFunction.arn}
      taskType: LAMBDA
      windowId: ${exampleAwsSsmMaintenanceWindow.id}
      targets:
        - key: InstanceIds
          values:
            - ${exampleAwsInstance.id}
      taskInvocationParameters:
        lambdaParameters:
          clientContext:
            fn::invoke:
              function: std:base64encode
              arguments:
                input: '{"key1":"value1"}'
              return: result
          payload: '{"key1":"value1"}'

The taskType property is set to LAMBDA. The lambdaParameters block configures the function invocation, including clientContext (base64-encoded metadata) and payload (JSON data passed to the function). The taskArn points to the Lambda function ARN to invoke.

Orchestrate workflows with Step Functions

Complex maintenance operations that require multi-step orchestration can trigger Step Functions state machines from maintenance windows.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.ssm.MaintenanceWindowTask("example", {
    maxConcurrency: "2",
    maxErrors: "1",
    priority: 1,
    taskArn: exampleAwsSfnActivity.id,
    taskType: "STEP_FUNCTIONS",
    windowId: exampleAwsSsmMaintenanceWindow.id,
    targets: [{
        key: "InstanceIds",
        values: [exampleAwsInstance.id],
    }],
    taskInvocationParameters: {
        stepFunctionsParameters: {
            input: "{\"key1\":\"value1\"}",
            name: "example",
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.ssm.MaintenanceWindowTask("example",
    max_concurrency="2",
    max_errors="1",
    priority=1,
    task_arn=example_aws_sfn_activity["id"],
    task_type="STEP_FUNCTIONS",
    window_id=example_aws_ssm_maintenance_window["id"],
    targets=[{
        "key": "InstanceIds",
        "values": [example_aws_instance["id"]],
    }],
    task_invocation_parameters={
        "step_functions_parameters": {
            "input": "{\"key1\":\"value1\"}",
            "name": "example",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ssm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ssm.NewMaintenanceWindowTask(ctx, "example", &ssm.MaintenanceWindowTaskArgs{
			MaxConcurrency: pulumi.String("2"),
			MaxErrors:      pulumi.String("1"),
			Priority:       pulumi.Int(1),
			TaskArn:        pulumi.Any(exampleAwsSfnActivity.Id),
			TaskType:       pulumi.String("STEP_FUNCTIONS"),
			WindowId:       pulumi.Any(exampleAwsSsmMaintenanceWindow.Id),
			Targets: ssm.MaintenanceWindowTaskTargetArray{
				&ssm.MaintenanceWindowTaskTargetArgs{
					Key: pulumi.String("InstanceIds"),
					Values: pulumi.StringArray{
						exampleAwsInstance.Id,
					},
				},
			},
			TaskInvocationParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersArgs{
				StepFunctionsParameters: &ssm.MaintenanceWindowTaskTaskInvocationParametersStepFunctionsParametersArgs{
					Input: pulumi.String("{\"key1\":\"value1\"}"),
					Name:  pulumi.String("example"),
				},
			},
		})
		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 example = new Aws.Ssm.MaintenanceWindowTask("example", new()
    {
        MaxConcurrency = "2",
        MaxErrors = "1",
        Priority = 1,
        TaskArn = exampleAwsSfnActivity.Id,
        TaskType = "STEP_FUNCTIONS",
        WindowId = exampleAwsSsmMaintenanceWindow.Id,
        Targets = new[]
        {
            new Aws.Ssm.Inputs.MaintenanceWindowTaskTargetArgs
            {
                Key = "InstanceIds",
                Values = new[]
                {
                    exampleAwsInstance.Id,
                },
            },
        },
        TaskInvocationParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersArgs
        {
            StepFunctionsParameters = new Aws.Ssm.Inputs.MaintenanceWindowTaskTaskInvocationParametersStepFunctionsParametersArgs
            {
                Input = "{\"key1\":\"value1\"}",
                Name = "example",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ssm.MaintenanceWindowTask;
import com.pulumi.aws.ssm.MaintenanceWindowTaskArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTargetArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersArgs;
import com.pulumi.aws.ssm.inputs.MaintenanceWindowTaskTaskInvocationParametersStepFunctionsParametersArgs;
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 example = new MaintenanceWindowTask("example", MaintenanceWindowTaskArgs.builder()
            .maxConcurrency("2")
            .maxErrors("1")
            .priority(1)
            .taskArn(exampleAwsSfnActivity.id())
            .taskType("STEP_FUNCTIONS")
            .windowId(exampleAwsSsmMaintenanceWindow.id())
            .targets(MaintenanceWindowTaskTargetArgs.builder()
                .key("InstanceIds")
                .values(exampleAwsInstance.id())
                .build())
            .taskInvocationParameters(MaintenanceWindowTaskTaskInvocationParametersArgs.builder()
                .stepFunctionsParameters(MaintenanceWindowTaskTaskInvocationParametersStepFunctionsParametersArgs.builder()
                    .input("{\"key1\":\"value1\"}")
                    .name("example")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ssm:MaintenanceWindowTask
    properties:
      maxConcurrency: 2
      maxErrors: 1
      priority: 1
      taskArn: ${exampleAwsSfnActivity.id}
      taskType: STEP_FUNCTIONS
      windowId: ${exampleAwsSsmMaintenanceWindow.id}
      targets:
        - key: InstanceIds
          values:
            - ${exampleAwsInstance.id}
      taskInvocationParameters:
        stepFunctionsParameters:
          input: '{"key1":"value1"}'
          name: example

The taskType property is set to STEP_FUNCTIONS. The stepFunctionsParameters block configures the workflow execution, including input (JSON data passed to the state machine) and name (execution identifier). The taskArn references the Step Functions activity ID.

Beyond these examples

These snippets focus on specific maintenance window task features: automation documents and shell commands, Lambda and Step Functions integration, and output capture and notifications. They’re intentionally minimal rather than full maintenance automation solutions.

The examples rely on pre-existing infrastructure such as maintenance windows, EC2 instances or window targets, IAM roles, S3 buckets, SNS topics (for Run Command), and Lambda functions or Step Functions activities (for respective task types). They focus on task configuration rather than provisioning the surrounding infrastructure.

To keep things focused, common task patterns are omitted, including:

  • Service role configuration (serviceRoleArn)
  • Cutoff behavior for long-running tasks (cutoffBehavior)
  • Priority ordering for multiple tasks (priority)
  • Concurrency and error thresholds (maxConcurrency, maxErrors)

These omissions are intentional: the goal is to illustrate how each task type is wired, not provide drop-in maintenance automation modules. See the SSM Maintenance Window Task resource reference for all available configuration options.

Let's configure AWS Systems Manager Maintenance Window Tasks

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Task Types & Configuration
What task types can I register in a maintenance window?
You can register four task types: AUTOMATION, LAMBDA, RUN_COMMAND, and STEP_FUNCTIONS.
What happens if I change the task type or window ID after creation?
Both taskType and windowId are immutable properties. Changing either forces resource replacement.
How do I configure parameters for different task types?

Use taskInvocationParameters with the appropriate nested block:

  • AUTOMATION - automationParameters with documentVersion and parameters
  • LAMBDA - lambdaParameters with clientContext and payload
  • RUN_COMMAND - runCommandParameters with S3 output, notifications, and timeout
  • STEP_FUNCTIONS - stepFunctionsParameters with input and name
Execution Control & Limits
How does task priority work in maintenance windows?
Lower numbers indicate higher priority. Tasks with the same priority run in parallel.
What's the difference between maxConcurrency and maxErrors?
maxConcurrency limits how many targets the task can run on simultaneously, while maxErrors sets the threshold for stopping task scheduling after failures.
Why are maxConcurrency and maxErrors string values instead of numbers?
Both maxConcurrency and maxErrors are defined as string types in the schema, even though they represent numeric limits.
What happens when the maintenance window cutoff time is reached?
Configure cutoffBehavior to control this: CONTINUE_TASK allows tasks to finish, while CANCEL_TASK stops them at cutoff.
Targeting & IAM
Do I need to provide a service role for task execution?
No, serviceRoleArn is optional. If not provided, Systems Manager uses your account’s service-linked role, creating one if it doesn’t exist.
How do I target specific instances vs window targets?
Use the targets array with Key=InstanceIds for specific instances or Key=WindowTargetIds for window target IDs.
Can I target both instances and window targets in the same task?
The targets property accepts either instance IDs or window target IDs, but the schema examples show single-key targeting patterns.

Using a different cloud?

Explore compute guides for other cloud providers: