Configure AWS CodeDeploy Deployment Groups

The aws:codedeploy/deploymentGroup:DeploymentGroup resource, part of the Pulumi AWS provider, defines a CodeDeploy deployment group that specifies which instances or services receive application revisions and how deployments execute. This guide focuses on three capabilities: EC2 tag-based targeting, ECS blue/green deployments, and Classic ELB traffic shifting.

Deployment groups require a CodeDeploy application, IAM service role, and target infrastructure such as EC2 instances, ECS services, or load balancers. The examples are intentionally small. Combine them with your own application definitions, IAM roles, and compute resources.

Deploy to EC2 instances with tag-based targeting

Most CodeDeploy workflows target EC2 instances using tags, allowing you to deploy application revisions to fleets without hardcoding instance IDs.

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

const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["codedeploy.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const example = new aws.iam.Role("example", {
    name: "example-role",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const aWSCodeDeployRole = new aws.iam.RolePolicyAttachment("AWSCodeDeployRole", {
    policyArn: "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole",
    role: example.name,
});
const exampleApplication = new aws.codedeploy.Application("example", {name: "example-app"});
const exampleTopic = new aws.sns.Topic("example", {name: "example-topic"});
const exampleDeploymentGroup = new aws.codedeploy.DeploymentGroup("example", {
    appName: exampleApplication.name,
    deploymentGroupName: "example-group",
    serviceRoleArn: example.arn,
    ec2TagSets: [{
        ec2TagFilters: [
            {
                key: "filterkey1",
                type: "KEY_AND_VALUE",
                value: "filtervalue",
            },
            {
                key: "filterkey2",
                type: "KEY_AND_VALUE",
                value: "filtervalue",
            },
        ],
    }],
    triggerConfigurations: [{
        triggerEvents: ["DeploymentFailure"],
        triggerName: "example-trigger",
        triggerTargetArn: exampleTopic.arn,
    }],
    autoRollbackConfiguration: {
        enabled: true,
        events: ["DEPLOYMENT_FAILURE"],
    },
    alarmConfiguration: {
        alarms: ["my-alarm-name"],
        enabled: true,
    },
    outdatedInstancesStrategy: "UPDATE",
});
import pulumi
import pulumi_aws as aws

assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["codedeploy.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
example = aws.iam.Role("example",
    name="example-role",
    assume_role_policy=assume_role.json)
a_ws_code_deploy_role = aws.iam.RolePolicyAttachment("AWSCodeDeployRole",
    policy_arn="arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole",
    role=example.name)
example_application = aws.codedeploy.Application("example", name="example-app")
example_topic = aws.sns.Topic("example", name="example-topic")
example_deployment_group = aws.codedeploy.DeploymentGroup("example",
    app_name=example_application.name,
    deployment_group_name="example-group",
    service_role_arn=example.arn,
    ec2_tag_sets=[{
        "ec2_tag_filters": [
            {
                "key": "filterkey1",
                "type": "KEY_AND_VALUE",
                "value": "filtervalue",
            },
            {
                "key": "filterkey2",
                "type": "KEY_AND_VALUE",
                "value": "filtervalue",
            },
        ],
    }],
    trigger_configurations=[{
        "trigger_events": ["DeploymentFailure"],
        "trigger_name": "example-trigger",
        "trigger_target_arn": example_topic.arn,
    }],
    auto_rollback_configuration={
        "enabled": True,
        "events": ["DEPLOYMENT_FAILURE"],
    },
    alarm_configuration={
        "alarms": ["my-alarm-name"],
        "enabled": True,
    },
    outdated_instances_strategy="UPDATE")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/codedeploy"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sns"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"codedeploy.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		example, err := iam.NewRole(ctx, "example", &iam.RoleArgs{
			Name:             pulumi.String("example-role"),
			AssumeRolePolicy: pulumi.String(assumeRole.Json),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "AWSCodeDeployRole", &iam.RolePolicyAttachmentArgs{
			PolicyArn: pulumi.String("arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole"),
			Role:      example.Name,
		})
		if err != nil {
			return err
		}
		exampleApplication, err := codedeploy.NewApplication(ctx, "example", &codedeploy.ApplicationArgs{
			Name: pulumi.String("example-app"),
		})
		if err != nil {
			return err
		}
		exampleTopic, err := sns.NewTopic(ctx, "example", &sns.TopicArgs{
			Name: pulumi.String("example-topic"),
		})
		if err != nil {
			return err
		}
		_, err = codedeploy.NewDeploymentGroup(ctx, "example", &codedeploy.DeploymentGroupArgs{
			AppName:             exampleApplication.Name,
			DeploymentGroupName: pulumi.String("example-group"),
			ServiceRoleArn:      example.Arn,
			Ec2TagSets: codedeploy.DeploymentGroupEc2TagSetArray{
				&codedeploy.DeploymentGroupEc2TagSetArgs{
					Ec2TagFilters: codedeploy.DeploymentGroupEc2TagSetEc2TagFilterArray{
						&codedeploy.DeploymentGroupEc2TagSetEc2TagFilterArgs{
							Key:   pulumi.String("filterkey1"),
							Type:  pulumi.String("KEY_AND_VALUE"),
							Value: pulumi.String("filtervalue"),
						},
						&codedeploy.DeploymentGroupEc2TagSetEc2TagFilterArgs{
							Key:   pulumi.String("filterkey2"),
							Type:  pulumi.String("KEY_AND_VALUE"),
							Value: pulumi.String("filtervalue"),
						},
					},
				},
			},
			TriggerConfigurations: codedeploy.DeploymentGroupTriggerConfigurationArray{
				&codedeploy.DeploymentGroupTriggerConfigurationArgs{
					TriggerEvents: pulumi.StringArray{
						pulumi.String("DeploymentFailure"),
					},
					TriggerName:      pulumi.String("example-trigger"),
					TriggerTargetArn: exampleTopic.Arn,
				},
			},
			AutoRollbackConfiguration: &codedeploy.DeploymentGroupAutoRollbackConfigurationArgs{
				Enabled: pulumi.Bool(true),
				Events: pulumi.StringArray{
					pulumi.String("DEPLOYMENT_FAILURE"),
				},
			},
			AlarmConfiguration: &codedeploy.DeploymentGroupAlarmConfigurationArgs{
				Alarms: pulumi.StringArray{
					pulumi.String("my-alarm-name"),
				},
				Enabled: pulumi.Bool(true),
			},
			OutdatedInstancesStrategy: pulumi.String("UPDATE"),
		})
		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 assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "codedeploy.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var example = new Aws.Iam.Role("example", new()
    {
        Name = "example-role",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var aWSCodeDeployRole = new Aws.Iam.RolePolicyAttachment("AWSCodeDeployRole", new()
    {
        PolicyArn = "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole",
        Role = example.Name,
    });

    var exampleApplication = new Aws.CodeDeploy.Application("example", new()
    {
        Name = "example-app",
    });

    var exampleTopic = new Aws.Sns.Topic("example", new()
    {
        Name = "example-topic",
    });

    var exampleDeploymentGroup = new Aws.CodeDeploy.DeploymentGroup("example", new()
    {
        AppName = exampleApplication.Name,
        DeploymentGroupName = "example-group",
        ServiceRoleArn = example.Arn,
        Ec2TagSets = new[]
        {
            new Aws.CodeDeploy.Inputs.DeploymentGroupEc2TagSetArgs
            {
                Ec2TagFilters = new[]
                {
                    new Aws.CodeDeploy.Inputs.DeploymentGroupEc2TagSetEc2TagFilterArgs
                    {
                        Key = "filterkey1",
                        Type = "KEY_AND_VALUE",
                        Value = "filtervalue",
                    },
                    new Aws.CodeDeploy.Inputs.DeploymentGroupEc2TagSetEc2TagFilterArgs
                    {
                        Key = "filterkey2",
                        Type = "KEY_AND_VALUE",
                        Value = "filtervalue",
                    },
                },
            },
        },
        TriggerConfigurations = new[]
        {
            new Aws.CodeDeploy.Inputs.DeploymentGroupTriggerConfigurationArgs
            {
                TriggerEvents = new[]
                {
                    "DeploymentFailure",
                },
                TriggerName = "example-trigger",
                TriggerTargetArn = exampleTopic.Arn,
            },
        },
        AutoRollbackConfiguration = new Aws.CodeDeploy.Inputs.DeploymentGroupAutoRollbackConfigurationArgs
        {
            Enabled = true,
            Events = new[]
            {
                "DEPLOYMENT_FAILURE",
            },
        },
        AlarmConfiguration = new Aws.CodeDeploy.Inputs.DeploymentGroupAlarmConfigurationArgs
        {
            Alarms = new[]
            {
                "my-alarm-name",
            },
            Enabled = true,
        },
        OutdatedInstancesStrategy = "UPDATE",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import com.pulumi.aws.codedeploy.Application;
import com.pulumi.aws.codedeploy.ApplicationArgs;
import com.pulumi.aws.sns.Topic;
import com.pulumi.aws.sns.TopicArgs;
import com.pulumi.aws.codedeploy.DeploymentGroup;
import com.pulumi.aws.codedeploy.DeploymentGroupArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupEc2TagSetArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupTriggerConfigurationArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupAutoRollbackConfigurationArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupAlarmConfigurationArgs;
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) {
        final var assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("codedeploy.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var example = new Role("example", RoleArgs.builder()
            .name("example-role")
            .assumeRolePolicy(assumeRole.json())
            .build());

        var aWSCodeDeployRole = new RolePolicyAttachment("aWSCodeDeployRole", RolePolicyAttachmentArgs.builder()
            .policyArn("arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole")
            .role(example.name())
            .build());

        var exampleApplication = new Application("exampleApplication", ApplicationArgs.builder()
            .name("example-app")
            .build());

        var exampleTopic = new Topic("exampleTopic", TopicArgs.builder()
            .name("example-topic")
            .build());

        var exampleDeploymentGroup = new DeploymentGroup("exampleDeploymentGroup", DeploymentGroupArgs.builder()
            .appName(exampleApplication.name())
            .deploymentGroupName("example-group")
            .serviceRoleArn(example.arn())
            .ec2TagSets(DeploymentGroupEc2TagSetArgs.builder()
                .ec2TagFilters(                
                    DeploymentGroupEc2TagSetEc2TagFilterArgs.builder()
                        .key("filterkey1")
                        .type("KEY_AND_VALUE")
                        .value("filtervalue")
                        .build(),
                    DeploymentGroupEc2TagSetEc2TagFilterArgs.builder()
                        .key("filterkey2")
                        .type("KEY_AND_VALUE")
                        .value("filtervalue")
                        .build())
                .build())
            .triggerConfigurations(DeploymentGroupTriggerConfigurationArgs.builder()
                .triggerEvents("DeploymentFailure")
                .triggerName("example-trigger")
                .triggerTargetArn(exampleTopic.arn())
                .build())
            .autoRollbackConfiguration(DeploymentGroupAutoRollbackConfigurationArgs.builder()
                .enabled(true)
                .events("DEPLOYMENT_FAILURE")
                .build())
            .alarmConfiguration(DeploymentGroupAlarmConfigurationArgs.builder()
                .alarms("my-alarm-name")
                .enabled(true)
                .build())
            .outdatedInstancesStrategy("UPDATE")
            .build());

    }
}
resources:
  example:
    type: aws:iam:Role
    properties:
      name: example-role
      assumeRolePolicy: ${assumeRole.json}
  aWSCodeDeployRole:
    type: aws:iam:RolePolicyAttachment
    name: AWSCodeDeployRole
    properties:
      policyArn: arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
      role: ${example.name}
  exampleApplication:
    type: aws:codedeploy:Application
    name: example
    properties:
      name: example-app
  exampleTopic:
    type: aws:sns:Topic
    name: example
    properties:
      name: example-topic
  exampleDeploymentGroup:
    type: aws:codedeploy:DeploymentGroup
    name: example
    properties:
      appName: ${exampleApplication.name}
      deploymentGroupName: example-group
      serviceRoleArn: ${example.arn}
      ec2TagSets:
        - ec2TagFilters:
            - key: filterkey1
              type: KEY_AND_VALUE
              value: filtervalue
            - key: filterkey2
              type: KEY_AND_VALUE
              value: filtervalue
      triggerConfigurations:
        - triggerEvents:
            - DeploymentFailure
          triggerName: example-trigger
          triggerTargetArn: ${exampleTopic.arn}
      autoRollbackConfiguration:
        enabled: true
        events:
          - DEPLOYMENT_FAILURE
      alarmConfiguration:
        alarms:
          - my-alarm-name
        enabled: true
      outdatedInstancesStrategy: UPDATE
variables:
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - codedeploy.amazonaws.com
            actions:
              - sts:AssumeRole

When a deployment runs, CodeDeploy queries for instances matching the ec2TagFilters criteria and deploys the application revision to them. The ec2TagSets property groups filters together; instances must match all filters within a set. The triggerConfigurations property sends SNS notifications on deployment events like failures. The autoRollbackConfiguration automatically reverts to the previous revision when deployments fail.

Deploy ECS services with blue/green traffic shifting

Container workloads on ECS benefit from blue/green deployments that provision a new task set, shift traffic gradually, and terminate old tasks only after validation.

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

const example = new aws.codedeploy.Application("example", {
    computePlatform: "ECS",
    name: "example",
});
const exampleDeploymentGroup = new aws.codedeploy.DeploymentGroup("example", {
    appName: example.name,
    deploymentConfigName: "CodeDeployDefault.ECSAllAtOnce",
    deploymentGroupName: "example",
    serviceRoleArn: exampleAwsIamRole.arn,
    autoRollbackConfiguration: {
        enabled: true,
        events: ["DEPLOYMENT_FAILURE"],
    },
    blueGreenDeploymentConfig: {
        deploymentReadyOption: {
            actionOnTimeout: "CONTINUE_DEPLOYMENT",
        },
        terminateBlueInstancesOnDeploymentSuccess: {
            action: "TERMINATE",
            terminationWaitTimeInMinutes: 5,
        },
    },
    deploymentStyle: {
        deploymentOption: "WITH_TRAFFIC_CONTROL",
        deploymentType: "BLUE_GREEN",
    },
    ecsService: {
        clusterName: exampleAwsEcsCluster.name,
        serviceName: exampleAwsEcsService.name,
    },
    loadBalancerInfo: {
        targetGroupPairInfo: {
            prodTrafficRoute: {
                listenerArns: [exampleAwsLbListener.arn],
            },
            targetGroups: [
                {
                    name: blue.name,
                },
                {
                    name: green.name,
                },
            ],
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.codedeploy.Application("example",
    compute_platform="ECS",
    name="example")
example_deployment_group = aws.codedeploy.DeploymentGroup("example",
    app_name=example.name,
    deployment_config_name="CodeDeployDefault.ECSAllAtOnce",
    deployment_group_name="example",
    service_role_arn=example_aws_iam_role["arn"],
    auto_rollback_configuration={
        "enabled": True,
        "events": ["DEPLOYMENT_FAILURE"],
    },
    blue_green_deployment_config={
        "deployment_ready_option": {
            "action_on_timeout": "CONTINUE_DEPLOYMENT",
        },
        "terminate_blue_instances_on_deployment_success": {
            "action": "TERMINATE",
            "termination_wait_time_in_minutes": 5,
        },
    },
    deployment_style={
        "deployment_option": "WITH_TRAFFIC_CONTROL",
        "deployment_type": "BLUE_GREEN",
    },
    ecs_service={
        "cluster_name": example_aws_ecs_cluster["name"],
        "service_name": example_aws_ecs_service["name"],
    },
    load_balancer_info={
        "target_group_pair_info": {
            "prod_traffic_route": {
                "listener_arns": [example_aws_lb_listener["arn"]],
            },
            "target_groups": [
                {
                    "name": blue["name"],
                },
                {
                    "name": green["name"],
                },
            ],
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := codedeploy.NewApplication(ctx, "example", &codedeploy.ApplicationArgs{
			ComputePlatform: pulumi.String("ECS"),
			Name:            pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = codedeploy.NewDeploymentGroup(ctx, "example", &codedeploy.DeploymentGroupArgs{
			AppName:              example.Name,
			DeploymentConfigName: pulumi.String("CodeDeployDefault.ECSAllAtOnce"),
			DeploymentGroupName:  pulumi.String("example"),
			ServiceRoleArn:       pulumi.Any(exampleAwsIamRole.Arn),
			AutoRollbackConfiguration: &codedeploy.DeploymentGroupAutoRollbackConfigurationArgs{
				Enabled: pulumi.Bool(true),
				Events: pulumi.StringArray{
					pulumi.String("DEPLOYMENT_FAILURE"),
				},
			},
			BlueGreenDeploymentConfig: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigArgs{
				DeploymentReadyOption: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs{
					ActionOnTimeout: pulumi.String("CONTINUE_DEPLOYMENT"),
				},
				TerminateBlueInstancesOnDeploymentSuccess: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs{
					Action:                       pulumi.String("TERMINATE"),
					TerminationWaitTimeInMinutes: pulumi.Int(5),
				},
			},
			DeploymentStyle: &codedeploy.DeploymentGroupDeploymentStyleArgs{
				DeploymentOption: pulumi.String("WITH_TRAFFIC_CONTROL"),
				DeploymentType:   pulumi.String("BLUE_GREEN"),
			},
			EcsService: &codedeploy.DeploymentGroupEcsServiceArgs{
				ClusterName: pulumi.Any(exampleAwsEcsCluster.Name),
				ServiceName: pulumi.Any(exampleAwsEcsService.Name),
			},
			LoadBalancerInfo: &codedeploy.DeploymentGroupLoadBalancerInfoArgs{
				TargetGroupPairInfo: &codedeploy.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoArgs{
					ProdTrafficRoute: &codedeploy.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoProdTrafficRouteArgs{
						ListenerArns: pulumi.StringArray{
							exampleAwsLbListener.Arn,
						},
					},
					TargetGroups: codedeploy.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArray{
						&codedeploy.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs{
							Name: pulumi.Any(blue.Name),
						},
						&codedeploy.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs{
							Name: pulumi.Any(green.Name),
						},
					},
				},
			},
		})
		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.CodeDeploy.Application("example", new()
    {
        ComputePlatform = "ECS",
        Name = "example",
    });

    var exampleDeploymentGroup = new Aws.CodeDeploy.DeploymentGroup("example", new()
    {
        AppName = example.Name,
        DeploymentConfigName = "CodeDeployDefault.ECSAllAtOnce",
        DeploymentGroupName = "example",
        ServiceRoleArn = exampleAwsIamRole.Arn,
        AutoRollbackConfiguration = new Aws.CodeDeploy.Inputs.DeploymentGroupAutoRollbackConfigurationArgs
        {
            Enabled = true,
            Events = new[]
            {
                "DEPLOYMENT_FAILURE",
            },
        },
        BlueGreenDeploymentConfig = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigArgs
        {
            DeploymentReadyOption = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs
            {
                ActionOnTimeout = "CONTINUE_DEPLOYMENT",
            },
            TerminateBlueInstancesOnDeploymentSuccess = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs
            {
                Action = "TERMINATE",
                TerminationWaitTimeInMinutes = 5,
            },
        },
        DeploymentStyle = new Aws.CodeDeploy.Inputs.DeploymentGroupDeploymentStyleArgs
        {
            DeploymentOption = "WITH_TRAFFIC_CONTROL",
            DeploymentType = "BLUE_GREEN",
        },
        EcsService = new Aws.CodeDeploy.Inputs.DeploymentGroupEcsServiceArgs
        {
            ClusterName = exampleAwsEcsCluster.Name,
            ServiceName = exampleAwsEcsService.Name,
        },
        LoadBalancerInfo = new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoArgs
        {
            TargetGroupPairInfo = new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoArgs
            {
                ProdTrafficRoute = new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoProdTrafficRouteArgs
                {
                    ListenerArns = new[]
                    {
                        exampleAwsLbListener.Arn,
                    },
                },
                TargetGroups = new[]
                {
                    new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs
                    {
                        Name = blue.Name,
                    },
                    new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs
                    {
                        Name = green.Name,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.codedeploy.Application;
import com.pulumi.aws.codedeploy.ApplicationArgs;
import com.pulumi.aws.codedeploy.DeploymentGroup;
import com.pulumi.aws.codedeploy.DeploymentGroupArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupAutoRollbackConfigurationArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupDeploymentStyleArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupEcsServiceArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupLoadBalancerInfoArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupLoadBalancerInfoTargetGroupPairInfoProdTrafficRouteArgs;
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 Application("example", ApplicationArgs.builder()
            .computePlatform("ECS")
            .name("example")
            .build());

        var exampleDeploymentGroup = new DeploymentGroup("exampleDeploymentGroup", DeploymentGroupArgs.builder()
            .appName(example.name())
            .deploymentConfigName("CodeDeployDefault.ECSAllAtOnce")
            .deploymentGroupName("example")
            .serviceRoleArn(exampleAwsIamRole.arn())
            .autoRollbackConfiguration(DeploymentGroupAutoRollbackConfigurationArgs.builder()
                .enabled(true)
                .events("DEPLOYMENT_FAILURE")
                .build())
            .blueGreenDeploymentConfig(DeploymentGroupBlueGreenDeploymentConfigArgs.builder()
                .deploymentReadyOption(DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs.builder()
                    .actionOnTimeout("CONTINUE_DEPLOYMENT")
                    .build())
                .terminateBlueInstancesOnDeploymentSuccess(DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs.builder()
                    .action("TERMINATE")
                    .terminationWaitTimeInMinutes(5)
                    .build())
                .build())
            .deploymentStyle(DeploymentGroupDeploymentStyleArgs.builder()
                .deploymentOption("WITH_TRAFFIC_CONTROL")
                .deploymentType("BLUE_GREEN")
                .build())
            .ecsService(DeploymentGroupEcsServiceArgs.builder()
                .clusterName(exampleAwsEcsCluster.name())
                .serviceName(exampleAwsEcsService.name())
                .build())
            .loadBalancerInfo(DeploymentGroupLoadBalancerInfoArgs.builder()
                .targetGroupPairInfo(DeploymentGroupLoadBalancerInfoTargetGroupPairInfoArgs.builder()
                    .prodTrafficRoute(DeploymentGroupLoadBalancerInfoTargetGroupPairInfoProdTrafficRouteArgs.builder()
                        .listenerArns(exampleAwsLbListener.arn())
                        .build())
                    .targetGroups(                    
                        DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs.builder()
                            .name(blue.name())
                            .build(),
                        DeploymentGroupLoadBalancerInfoTargetGroupPairInfoTargetGroupArgs.builder()
                            .name(green.name())
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:codedeploy:Application
    properties:
      computePlatform: ECS
      name: example
  exampleDeploymentGroup:
    type: aws:codedeploy:DeploymentGroup
    name: example
    properties:
      appName: ${example.name}
      deploymentConfigName: CodeDeployDefault.ECSAllAtOnce
      deploymentGroupName: example
      serviceRoleArn: ${exampleAwsIamRole.arn}
      autoRollbackConfiguration:
        enabled: true
        events:
          - DEPLOYMENT_FAILURE
      blueGreenDeploymentConfig:
        deploymentReadyOption:
          actionOnTimeout: CONTINUE_DEPLOYMENT
        terminateBlueInstancesOnDeploymentSuccess:
          action: TERMINATE
          terminationWaitTimeInMinutes: 5
      deploymentStyle:
        deploymentOption: WITH_TRAFFIC_CONTROL
        deploymentType: BLUE_GREEN
      ecsService:
        clusterName: ${exampleAwsEcsCluster.name}
        serviceName: ${exampleAwsEcsService.name}
      loadBalancerInfo:
        targetGroupPairInfo:
          prodTrafficRoute:
            listenerArns:
              - ${exampleAwsLbListener.arn}
          targetGroups:
            - name: ${blue.name}
            - name: ${green.name}

The deploymentStyle property sets the deployment type to BLUE_GREEN and enables traffic control through the load balancer. The blueGreenDeploymentConfig controls timing: deploymentReadyOption determines when traffic shifts (here, immediately), and terminateBlueInstancesOnDeploymentSuccess waits 5 minutes before terminating old tasks. The loadBalancerInfo property connects the deployment to your ALB listener and target groups, enabling CodeDeploy to shift traffic between blue and green task sets.

Deploy to EC2 with Classic ELB traffic control

Applications using Classic Load Balancers can perform blue/green deployments by discovering existing instances and controlling when old instances terminate.

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

const example = new aws.codedeploy.Application("example", {name: "example-app"});
const exampleDeploymentGroup = new aws.codedeploy.DeploymentGroup("example", {
    appName: example.name,
    deploymentGroupName: "example-group",
    serviceRoleArn: exampleAwsIamRole.arn,
    deploymentStyle: {
        deploymentOption: "WITH_TRAFFIC_CONTROL",
        deploymentType: "BLUE_GREEN",
    },
    loadBalancerInfo: {
        elbInfos: [{
            name: exampleAwsElb.name,
        }],
    },
    blueGreenDeploymentConfig: {
        deploymentReadyOption: {
            actionOnTimeout: "STOP_DEPLOYMENT",
            waitTimeInMinutes: 60,
        },
        greenFleetProvisioningOption: {
            action: "DISCOVER_EXISTING",
        },
        terminateBlueInstancesOnDeploymentSuccess: {
            action: "KEEP_ALIVE",
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.codedeploy.Application("example", name="example-app")
example_deployment_group = aws.codedeploy.DeploymentGroup("example",
    app_name=example.name,
    deployment_group_name="example-group",
    service_role_arn=example_aws_iam_role["arn"],
    deployment_style={
        "deployment_option": "WITH_TRAFFIC_CONTROL",
        "deployment_type": "BLUE_GREEN",
    },
    load_balancer_info={
        "elb_infos": [{
            "name": example_aws_elb["name"],
        }],
    },
    blue_green_deployment_config={
        "deployment_ready_option": {
            "action_on_timeout": "STOP_DEPLOYMENT",
            "wait_time_in_minutes": 60,
        },
        "green_fleet_provisioning_option": {
            "action": "DISCOVER_EXISTING",
        },
        "terminate_blue_instances_on_deployment_success": {
            "action": "KEEP_ALIVE",
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := codedeploy.NewApplication(ctx, "example", &codedeploy.ApplicationArgs{
			Name: pulumi.String("example-app"),
		})
		if err != nil {
			return err
		}
		_, err = codedeploy.NewDeploymentGroup(ctx, "example", &codedeploy.DeploymentGroupArgs{
			AppName:             example.Name,
			DeploymentGroupName: pulumi.String("example-group"),
			ServiceRoleArn:      pulumi.Any(exampleAwsIamRole.Arn),
			DeploymentStyle: &codedeploy.DeploymentGroupDeploymentStyleArgs{
				DeploymentOption: pulumi.String("WITH_TRAFFIC_CONTROL"),
				DeploymentType:   pulumi.String("BLUE_GREEN"),
			},
			LoadBalancerInfo: &codedeploy.DeploymentGroupLoadBalancerInfoArgs{
				ElbInfos: codedeploy.DeploymentGroupLoadBalancerInfoElbInfoArray{
					&codedeploy.DeploymentGroupLoadBalancerInfoElbInfoArgs{
						Name: pulumi.Any(exampleAwsElb.Name),
					},
				},
			},
			BlueGreenDeploymentConfig: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigArgs{
				DeploymentReadyOption: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs{
					ActionOnTimeout:   pulumi.String("STOP_DEPLOYMENT"),
					WaitTimeInMinutes: pulumi.Int(60),
				},
				GreenFleetProvisioningOption: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigGreenFleetProvisioningOptionArgs{
					Action: pulumi.String("DISCOVER_EXISTING"),
				},
				TerminateBlueInstancesOnDeploymentSuccess: &codedeploy.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs{
					Action: pulumi.String("KEEP_ALIVE"),
				},
			},
		})
		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.CodeDeploy.Application("example", new()
    {
        Name = "example-app",
    });

    var exampleDeploymentGroup = new Aws.CodeDeploy.DeploymentGroup("example", new()
    {
        AppName = example.Name,
        DeploymentGroupName = "example-group",
        ServiceRoleArn = exampleAwsIamRole.Arn,
        DeploymentStyle = new Aws.CodeDeploy.Inputs.DeploymentGroupDeploymentStyleArgs
        {
            DeploymentOption = "WITH_TRAFFIC_CONTROL",
            DeploymentType = "BLUE_GREEN",
        },
        LoadBalancerInfo = new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoArgs
        {
            ElbInfos = new[]
            {
                new Aws.CodeDeploy.Inputs.DeploymentGroupLoadBalancerInfoElbInfoArgs
                {
                    Name = exampleAwsElb.Name,
                },
            },
        },
        BlueGreenDeploymentConfig = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigArgs
        {
            DeploymentReadyOption = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs
            {
                ActionOnTimeout = "STOP_DEPLOYMENT",
                WaitTimeInMinutes = 60,
            },
            GreenFleetProvisioningOption = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigGreenFleetProvisioningOptionArgs
            {
                Action = "DISCOVER_EXISTING",
            },
            TerminateBlueInstancesOnDeploymentSuccess = new Aws.CodeDeploy.Inputs.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs
            {
                Action = "KEEP_ALIVE",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.codedeploy.Application;
import com.pulumi.aws.codedeploy.ApplicationArgs;
import com.pulumi.aws.codedeploy.DeploymentGroup;
import com.pulumi.aws.codedeploy.DeploymentGroupArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupDeploymentStyleArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupLoadBalancerInfoArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigGreenFleetProvisioningOptionArgs;
import com.pulumi.aws.codedeploy.inputs.DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs;
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 Application("example", ApplicationArgs.builder()
            .name("example-app")
            .build());

        var exampleDeploymentGroup = new DeploymentGroup("exampleDeploymentGroup", DeploymentGroupArgs.builder()
            .appName(example.name())
            .deploymentGroupName("example-group")
            .serviceRoleArn(exampleAwsIamRole.arn())
            .deploymentStyle(DeploymentGroupDeploymentStyleArgs.builder()
                .deploymentOption("WITH_TRAFFIC_CONTROL")
                .deploymentType("BLUE_GREEN")
                .build())
            .loadBalancerInfo(DeploymentGroupLoadBalancerInfoArgs.builder()
                .elbInfos(DeploymentGroupLoadBalancerInfoElbInfoArgs.builder()
                    .name(exampleAwsElb.name())
                    .build())
                .build())
            .blueGreenDeploymentConfig(DeploymentGroupBlueGreenDeploymentConfigArgs.builder()
                .deploymentReadyOption(DeploymentGroupBlueGreenDeploymentConfigDeploymentReadyOptionArgs.builder()
                    .actionOnTimeout("STOP_DEPLOYMENT")
                    .waitTimeInMinutes(60)
                    .build())
                .greenFleetProvisioningOption(DeploymentGroupBlueGreenDeploymentConfigGreenFleetProvisioningOptionArgs.builder()
                    .action("DISCOVER_EXISTING")
                    .build())
                .terminateBlueInstancesOnDeploymentSuccess(DeploymentGroupBlueGreenDeploymentConfigTerminateBlueInstancesOnDeploymentSuccessArgs.builder()
                    .action("KEEP_ALIVE")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:codedeploy:Application
    properties:
      name: example-app
  exampleDeploymentGroup:
    type: aws:codedeploy:DeploymentGroup
    name: example
    properties:
      appName: ${example.name}
      deploymentGroupName: example-group
      serviceRoleArn: ${exampleAwsIamRole.arn}
      deploymentStyle:
        deploymentOption: WITH_TRAFFIC_CONTROL
        deploymentType: BLUE_GREEN
      loadBalancerInfo:
        elbInfos:
          - name: ${exampleAwsElb.name}
      blueGreenDeploymentConfig:
        deploymentReadyOption:
          actionOnTimeout: STOP_DEPLOYMENT
          waitTimeInMinutes: 60
        greenFleetProvisioningOption:
          action: DISCOVER_EXISTING
        terminateBlueInstancesOnDeploymentSuccess:
          action: KEEP_ALIVE

The greenFleetProvisioningOption with DISCOVER_EXISTING tells CodeDeploy to use pre-provisioned instances rather than creating new ones. The deploymentReadyOption with STOP_DEPLOYMENT pauses for manual approval before shifting traffic. The terminateBlueInstancesOnDeploymentSuccess with KEEP_ALIVE preserves old instances after deployment, allowing you to manage their lifecycle separately.

Beyond these examples

These snippets focus on specific deployment group features: EC2 tag-based targeting and ECS service deployments, blue/green deployment configuration, and load balancer integration and traffic control. They’re intentionally minimal rather than full deployment pipelines.

The examples rely on pre-existing infrastructure such as CodeDeploy applications, IAM roles with deployment permissions, EC2 instances, ECS clusters, or load balancers, and SNS topics for notifications. They focus on configuring the deployment group rather than provisioning the surrounding infrastructure.

To keep things focused, common deployment group patterns are omitted, including:

  • Auto Scaling group integration (autoscalingGroups)
  • On-premises instance targeting (onPremisesInstanceTagFilters)
  • Alarm-based deployment controls (alarmConfiguration)
  • Termination hooks for Auto Scaling (terminationHookEnabled)

These omissions are intentional: the goal is to illustrate how each deployment group feature is wired, not provide drop-in CI/CD modules. See the CodeDeploy DeploymentGroup resource reference for all available configuration options.

Let's configure AWS CodeDeploy Deployment Groups

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Blue/Green Deployments
Why is my blue/green deployment creating conflicting Auto Scaling Groups?
Using greenFleetProvisioningOption with the COPY_AUTO_SCALING_GROUP action causes CodeDeploy to create a new Auto Scaling Group that isn’t managed by Pulumi, leading to configuration conflicts. Use DISCOVER_EXISTING with separate blue and green Auto Scaling Groups instead.
How do I configure blue/green deployments for ECS?
Set deploymentStyle with deploymentType: BLUE_GREEN and deploymentOption: WITH_TRAFFIC_CONTROL. Configure ecsService with your cluster and service names, and use loadBalancerInfo with targetGroupPairInfo to define production traffic routes and target groups.
How do I use a Classic ELB for blue/green deployments?
Configure loadBalancerInfo with elbInfos containing your ELB name, and set deploymentStyle to BLUE_GREEN with WITH_TRAFFIC_CONTROL.
IAM & Permissions
What IAM role configuration is required for a deployment group?
Create an IAM role with a trust policy allowing codedeploy.amazonaws.com to assume it, then attach the AWS managed policy arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole. Pass the role’s ARN to serviceRoleArn.
Instance Targeting & Scaling
How do I target specific EC2 instances for deployment?
Use ec2TagFilters or ec2TagSets to specify tag-based filters. Each filter includes key, type (such as KEY_AND_VALUE), and value to match your instances.
What happens to instances launched during an active deployment?
The outdatedInstancesStrategy controls this behavior. The default UPDATE ensures new instances receive the deployment. Set to IGNORE if you want new instances to skip the current deployment.
Monitoring & Rollback
How do I enable automatic rollback on deployment failure?
Configure autoRollbackConfiguration with enabled: true and specify events such as DEPLOYMENT_FAILURE to trigger automatic rollback.
How do I set up CloudWatch alarms for deployments?
Use alarmConfiguration to specify alarm names and set enabled: true. CodeDeploy will monitor these alarms during deployment.
How do I get SNS notifications for deployment events?
Configure triggerConfigurations with triggerEvents (like DeploymentFailure), a triggerName, and triggerTargetArn pointing to your SNS topic.
Deployment Configuration
What's the default deployment configuration?
The default is CodeDeployDefault.OneAtATime, which deploys to one instance at a time. You can customize this using deploymentConfigName.
What deployment types are available?
Use deploymentStyle to choose between in-place deployments (update existing instances) or blue/green deployments (provision new instances). Set deploymentOption to WITH_TRAFFIC_CONTROL to route traffic through a load balancer.
Can I import an existing deployment group into Pulumi?
Yes, use pulumi import with the format app_name:deployment_group_name, for example: pulumi import aws:codedeploy/deploymentGroup:DeploymentGroup example my-application:my-deployment-group.

Using a different cloud?

Explore integration guides for other cloud providers: