Configure AWS VPC Lattice Listeners

The aws:vpclattice/listener:Listener resource, part of the Pulumi AWS provider, defines a VPC Lattice listener that accepts traffic on a service and routes it according to configured actions. This guide focuses on two capabilities: fixed response actions for static replies, and single and weighted target group forwarding.

Listeners belong to VPC Lattice services and forward traffic to target groups containing your application backends. The examples are intentionally small. Combine them with your own VPC Lattice services, target groups, and routing rules.

Return a fixed HTTP response without backend targets

Some listeners return static responses for maintenance pages, health checks, or default catch-all routes.

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

const example = new aws.vpclattice.Service("example", {name: "example"});
const exampleListener = new aws.vpclattice.Listener("example", {
    name: "example",
    protocol: "HTTPS",
    serviceIdentifier: example.id,
    defaultAction: {
        fixedResponse: {
            statusCode: 404,
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.vpclattice.Service("example", name="example")
example_listener = aws.vpclattice.Listener("example",
    name="example",
    protocol="HTTPS",
    service_identifier=example.id,
    default_action={
        "fixed_response": {
            "status_code": 404,
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := vpclattice.NewService(ctx, "example", &vpclattice.ServiceArgs{
			Name: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = vpclattice.NewListener(ctx, "example", &vpclattice.ListenerArgs{
			Name:              pulumi.String("example"),
			Protocol:          pulumi.String("HTTPS"),
			ServiceIdentifier: example.ID(),
			DefaultAction: &vpclattice.ListenerDefaultActionArgs{
				FixedResponse: &vpclattice.ListenerDefaultActionFixedResponseArgs{
					StatusCode: pulumi.Int(404),
				},
			},
		})
		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.VpcLattice.Service("example", new()
    {
        Name = "example",
    });

    var exampleListener = new Aws.VpcLattice.Listener("example", new()
    {
        Name = "example",
        Protocol = "HTTPS",
        ServiceIdentifier = example.Id,
        DefaultAction = new Aws.VpcLattice.Inputs.ListenerDefaultActionArgs
        {
            FixedResponse = new Aws.VpcLattice.Inputs.ListenerDefaultActionFixedResponseArgs
            {
                StatusCode = 404,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.vpclattice.Service;
import com.pulumi.aws.vpclattice.ServiceArgs;
import com.pulumi.aws.vpclattice.Listener;
import com.pulumi.aws.vpclattice.ListenerArgs;
import com.pulumi.aws.vpclattice.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.vpclattice.inputs.ListenerDefaultActionFixedResponseArgs;
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 Service("example", ServiceArgs.builder()
            .name("example")
            .build());

        var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
            .name("example")
            .protocol("HTTPS")
            .serviceIdentifier(example.id())
            .defaultAction(ListenerDefaultActionArgs.builder()
                .fixedResponse(ListenerDefaultActionFixedResponseArgs.builder()
                    .statusCode(404)
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:vpclattice:Service
    properties:
      name: example
  exampleListener:
    type: aws:vpclattice:Listener
    name: example
    properties:
      name: example
      protocol: HTTPS
      serviceIdentifier: ${example.id}
      defaultAction:
        fixedResponse:
          statusCode: 404

The defaultAction property defines what happens when traffic arrives. A fixedResponse returns the specified statusCode directly without forwarding to any backend. The protocol property determines the listener’s communication protocol; serviceIdentifier links the listener to its parent VPC Lattice service.

Route traffic to a single target group

Most listeners forward incoming requests to a target group containing EC2 instances, Lambda functions, or IP addresses.

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

const example = new aws.vpclattice.Service("example", {name: "example"});
const exampleTargetGroup = new aws.vpclattice.TargetGroup("example", {
    name: "example-target-group-1",
    type: "INSTANCE",
    config: {
        port: 80,
        protocol: "HTTP",
        vpcIdentifier: exampleAwsVpc.id,
    },
});
const exampleListener = new aws.vpclattice.Listener("example", {
    name: "example",
    protocol: "HTTP",
    serviceIdentifier: example.id,
    defaultAction: {
        forwards: [{
            targetGroups: [{
                targetGroupIdentifier: exampleTargetGroup.id,
            }],
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.vpclattice.Service("example", name="example")
example_target_group = aws.vpclattice.TargetGroup("example",
    name="example-target-group-1",
    type="INSTANCE",
    config={
        "port": 80,
        "protocol": "HTTP",
        "vpc_identifier": example_aws_vpc["id"],
    })
example_listener = aws.vpclattice.Listener("example",
    name="example",
    protocol="HTTP",
    service_identifier=example.id,
    default_action={
        "forwards": [{
            "target_groups": [{
                "target_group_identifier": example_target_group.id,
            }],
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := vpclattice.NewService(ctx, "example", &vpclattice.ServiceArgs{
			Name: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		exampleTargetGroup, err := vpclattice.NewTargetGroup(ctx, "example", &vpclattice.TargetGroupArgs{
			Name: pulumi.String("example-target-group-1"),
			Type: pulumi.String("INSTANCE"),
			Config: &vpclattice.TargetGroupConfigArgs{
				Port:          pulumi.Int(80),
				Protocol:      pulumi.String("HTTP"),
				VpcIdentifier: pulumi.Any(exampleAwsVpc.Id),
			},
		})
		if err != nil {
			return err
		}
		_, err = vpclattice.NewListener(ctx, "example", &vpclattice.ListenerArgs{
			Name:              pulumi.String("example"),
			Protocol:          pulumi.String("HTTP"),
			ServiceIdentifier: example.ID(),
			DefaultAction: &vpclattice.ListenerDefaultActionArgs{
				Forwards: vpclattice.ListenerDefaultActionForwardArray{
					&vpclattice.ListenerDefaultActionForwardArgs{
						TargetGroups: vpclattice.ListenerDefaultActionForwardTargetGroupArray{
							&vpclattice.ListenerDefaultActionForwardTargetGroupArgs{
								TargetGroupIdentifier: exampleTargetGroup.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.VpcLattice.Service("example", new()
    {
        Name = "example",
    });

    var exampleTargetGroup = new Aws.VpcLattice.TargetGroup("example", new()
    {
        Name = "example-target-group-1",
        Type = "INSTANCE",
        Config = new Aws.VpcLattice.Inputs.TargetGroupConfigArgs
        {
            Port = 80,
            Protocol = "HTTP",
            VpcIdentifier = exampleAwsVpc.Id,
        },
    });

    var exampleListener = new Aws.VpcLattice.Listener("example", new()
    {
        Name = "example",
        Protocol = "HTTP",
        ServiceIdentifier = example.Id,
        DefaultAction = new Aws.VpcLattice.Inputs.ListenerDefaultActionArgs
        {
            Forwards = new[]
            {
                new Aws.VpcLattice.Inputs.ListenerDefaultActionForwardArgs
                {
                    TargetGroups = new[]
                    {
                        new Aws.VpcLattice.Inputs.ListenerDefaultActionForwardTargetGroupArgs
                        {
                            TargetGroupIdentifier = exampleTargetGroup.Id,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.vpclattice.Service;
import com.pulumi.aws.vpclattice.ServiceArgs;
import com.pulumi.aws.vpclattice.TargetGroup;
import com.pulumi.aws.vpclattice.TargetGroupArgs;
import com.pulumi.aws.vpclattice.inputs.TargetGroupConfigArgs;
import com.pulumi.aws.vpclattice.Listener;
import com.pulumi.aws.vpclattice.ListenerArgs;
import com.pulumi.aws.vpclattice.inputs.ListenerDefaultActionArgs;
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 Service("example", ServiceArgs.builder()
            .name("example")
            .build());

        var exampleTargetGroup = new TargetGroup("exampleTargetGroup", TargetGroupArgs.builder()
            .name("example-target-group-1")
            .type("INSTANCE")
            .config(TargetGroupConfigArgs.builder()
                .port(80)
                .protocol("HTTP")
                .vpcIdentifier(exampleAwsVpc.id())
                .build())
            .build());

        var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
            .name("example")
            .protocol("HTTP")
            .serviceIdentifier(example.id())
            .defaultAction(ListenerDefaultActionArgs.builder()
                .forwards(ListenerDefaultActionForwardArgs.builder()
                    .targetGroups(ListenerDefaultActionForwardTargetGroupArgs.builder()
                        .targetGroupIdentifier(exampleTargetGroup.id())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:vpclattice:Service
    properties:
      name: example
  exampleTargetGroup:
    type: aws:vpclattice:TargetGroup
    name: example
    properties:
      name: example-target-group-1
      type: INSTANCE
      config:
        port: 80
        protocol: HTTP
        vpcIdentifier: ${exampleAwsVpc.id}
  exampleListener:
    type: aws:vpclattice:Listener
    name: example
    properties:
      name: example
      protocol: HTTP
      serviceIdentifier: ${example.id}
      defaultAction:
        forwards:
          - targetGroups:
              - targetGroupIdentifier: ${exampleTargetGroup.id}

When defaultAction contains a forwards block, the listener routes traffic to the specified target groups. The targetGroupIdentifier points to the backend that processes requests. This is the starting point for traffic routing; you can extend it with multiple target groups and weights.

Split traffic across multiple target groups with weights

Blue-green deployments and canary releases distribute traffic across multiple backend versions according to percentage weights.

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

const example = new aws.vpclattice.Service("example", {name: "example"});
const example1 = new aws.vpclattice.TargetGroup("example1", {
    name: "example-target-group-1",
    type: "INSTANCE",
    config: {
        port: 80,
        protocol: "HTTP",
        vpcIdentifier: exampleAwsVpc.id,
    },
});
const example2 = new aws.vpclattice.TargetGroup("example2", {
    name: "example-target-group-2",
    type: "INSTANCE",
    config: {
        port: 8080,
        protocol: "HTTP",
        vpcIdentifier: exampleAwsVpc.id,
    },
});
const exampleListener = new aws.vpclattice.Listener("example", {
    name: "example",
    protocol: "HTTP",
    serviceIdentifier: example.id,
    defaultAction: {
        forwards: [{
            targetGroups: [
                {
                    targetGroupIdentifier: example1.id,
                    weight: 80,
                },
                {
                    targetGroupIdentifier: example2.id,
                    weight: 20,
                },
            ],
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.vpclattice.Service("example", name="example")
example1 = aws.vpclattice.TargetGroup("example1",
    name="example-target-group-1",
    type="INSTANCE",
    config={
        "port": 80,
        "protocol": "HTTP",
        "vpc_identifier": example_aws_vpc["id"],
    })
example2 = aws.vpclattice.TargetGroup("example2",
    name="example-target-group-2",
    type="INSTANCE",
    config={
        "port": 8080,
        "protocol": "HTTP",
        "vpc_identifier": example_aws_vpc["id"],
    })
example_listener = aws.vpclattice.Listener("example",
    name="example",
    protocol="HTTP",
    service_identifier=example.id,
    default_action={
        "forwards": [{
            "target_groups": [
                {
                    "target_group_identifier": example1.id,
                    "weight": 80,
                },
                {
                    "target_group_identifier": example2.id,
                    "weight": 20,
                },
            ],
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := vpclattice.NewService(ctx, "example", &vpclattice.ServiceArgs{
			Name: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		example1, err := vpclattice.NewTargetGroup(ctx, "example1", &vpclattice.TargetGroupArgs{
			Name: pulumi.String("example-target-group-1"),
			Type: pulumi.String("INSTANCE"),
			Config: &vpclattice.TargetGroupConfigArgs{
				Port:          pulumi.Int(80),
				Protocol:      pulumi.String("HTTP"),
				VpcIdentifier: pulumi.Any(exampleAwsVpc.Id),
			},
		})
		if err != nil {
			return err
		}
		example2, err := vpclattice.NewTargetGroup(ctx, "example2", &vpclattice.TargetGroupArgs{
			Name: pulumi.String("example-target-group-2"),
			Type: pulumi.String("INSTANCE"),
			Config: &vpclattice.TargetGroupConfigArgs{
				Port:          pulumi.Int(8080),
				Protocol:      pulumi.String("HTTP"),
				VpcIdentifier: pulumi.Any(exampleAwsVpc.Id),
			},
		})
		if err != nil {
			return err
		}
		_, err = vpclattice.NewListener(ctx, "example", &vpclattice.ListenerArgs{
			Name:              pulumi.String("example"),
			Protocol:          pulumi.String("HTTP"),
			ServiceIdentifier: example.ID(),
			DefaultAction: &vpclattice.ListenerDefaultActionArgs{
				Forwards: vpclattice.ListenerDefaultActionForwardArray{
					&vpclattice.ListenerDefaultActionForwardArgs{
						TargetGroups: vpclattice.ListenerDefaultActionForwardTargetGroupArray{
							&vpclattice.ListenerDefaultActionForwardTargetGroupArgs{
								TargetGroupIdentifier: example1.ID(),
								Weight:                pulumi.Int(80),
							},
							&vpclattice.ListenerDefaultActionForwardTargetGroupArgs{
								TargetGroupIdentifier: example2.ID(),
								Weight:                pulumi.Int(20),
							},
						},
					},
				},
			},
		})
		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.VpcLattice.Service("example", new()
    {
        Name = "example",
    });

    var example1 = new Aws.VpcLattice.TargetGroup("example1", new()
    {
        Name = "example-target-group-1",
        Type = "INSTANCE",
        Config = new Aws.VpcLattice.Inputs.TargetGroupConfigArgs
        {
            Port = 80,
            Protocol = "HTTP",
            VpcIdentifier = exampleAwsVpc.Id,
        },
    });

    var example2 = new Aws.VpcLattice.TargetGroup("example2", new()
    {
        Name = "example-target-group-2",
        Type = "INSTANCE",
        Config = new Aws.VpcLattice.Inputs.TargetGroupConfigArgs
        {
            Port = 8080,
            Protocol = "HTTP",
            VpcIdentifier = exampleAwsVpc.Id,
        },
    });

    var exampleListener = new Aws.VpcLattice.Listener("example", new()
    {
        Name = "example",
        Protocol = "HTTP",
        ServiceIdentifier = example.Id,
        DefaultAction = new Aws.VpcLattice.Inputs.ListenerDefaultActionArgs
        {
            Forwards = new[]
            {
                new Aws.VpcLattice.Inputs.ListenerDefaultActionForwardArgs
                {
                    TargetGroups = new[]
                    {
                        new Aws.VpcLattice.Inputs.ListenerDefaultActionForwardTargetGroupArgs
                        {
                            TargetGroupIdentifier = example1.Id,
                            Weight = 80,
                        },
                        new Aws.VpcLattice.Inputs.ListenerDefaultActionForwardTargetGroupArgs
                        {
                            TargetGroupIdentifier = example2.Id,
                            Weight = 20,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.vpclattice.Service;
import com.pulumi.aws.vpclattice.ServiceArgs;
import com.pulumi.aws.vpclattice.TargetGroup;
import com.pulumi.aws.vpclattice.TargetGroupArgs;
import com.pulumi.aws.vpclattice.inputs.TargetGroupConfigArgs;
import com.pulumi.aws.vpclattice.Listener;
import com.pulumi.aws.vpclattice.ListenerArgs;
import com.pulumi.aws.vpclattice.inputs.ListenerDefaultActionArgs;
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 Service("example", ServiceArgs.builder()
            .name("example")
            .build());

        var example1 = new TargetGroup("example1", TargetGroupArgs.builder()
            .name("example-target-group-1")
            .type("INSTANCE")
            .config(TargetGroupConfigArgs.builder()
                .port(80)
                .protocol("HTTP")
                .vpcIdentifier(exampleAwsVpc.id())
                .build())
            .build());

        var example2 = new TargetGroup("example2", TargetGroupArgs.builder()
            .name("example-target-group-2")
            .type("INSTANCE")
            .config(TargetGroupConfigArgs.builder()
                .port(8080)
                .protocol("HTTP")
                .vpcIdentifier(exampleAwsVpc.id())
                .build())
            .build());

        var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
            .name("example")
            .protocol("HTTP")
            .serviceIdentifier(example.id())
            .defaultAction(ListenerDefaultActionArgs.builder()
                .forwards(ListenerDefaultActionForwardArgs.builder()
                    .targetGroups(                    
                        ListenerDefaultActionForwardTargetGroupArgs.builder()
                            .targetGroupIdentifier(example1.id())
                            .weight(80)
                            .build(),
                        ListenerDefaultActionForwardTargetGroupArgs.builder()
                            .targetGroupIdentifier(example2.id())
                            .weight(20)
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:vpclattice:Service
    properties:
      name: example
  example1:
    type: aws:vpclattice:TargetGroup
    properties:
      name: example-target-group-1
      type: INSTANCE
      config:
        port: 80
        protocol: HTTP
        vpcIdentifier: ${exampleAwsVpc.id}
  example2:
    type: aws:vpclattice:TargetGroup
    properties:
      name: example-target-group-2
      type: INSTANCE
      config:
        port: 8080
        protocol: HTTP
        vpcIdentifier: ${exampleAwsVpc.id}
  exampleListener:
    type: aws:vpclattice:Listener
    name: example
    properties:
      name: example
      protocol: HTTP
      serviceIdentifier: ${example.id}
      defaultAction:
        forwards:
          - targetGroups:
              - targetGroupIdentifier: ${example1.id}
                weight: 80
              - targetGroupIdentifier: ${example2.id}
                weight: 20

The weight property controls traffic distribution across target groups. Here, 80% of requests go to the first target group and 20% to the second. Weights must sum to 100 across all target groups in a forwards block. This extends basic forwarding by enabling gradual traffic shifts between application versions.

Beyond these examples

These snippets focus on specific listener-level features: fixed responses and target group forwarding, and weighted traffic distribution. They’re intentionally minimal rather than full service mesh configurations.

The examples reference pre-existing infrastructure such as VPC Lattice services, target groups with configured backends, and VPC infrastructure. They focus on configuring the listener rather than provisioning the surrounding service mesh.

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

  • Port configuration (defaults to 80 for HTTP, 443 for HTTPS)
  • HTTPS and TLS_PASSTHROUGH protocols
  • Listener rules beyond the default action
  • Tags for resource organization

These omissions are intentional: the goal is to illustrate how each listener feature is wired, not provide drop-in service mesh modules. See the VPC Lattice Listener resource reference for all available configuration options.

Let's configure AWS VPC Lattice Listeners

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Setup
Do I need to provide serviceArn or serviceIdentifier?
You must provide either serviceArn or serviceIdentifier to associate the listener with a VPC Lattice service, but not both.
What are the naming requirements for a listener?
Listener names must be unique within a service and can only contain lowercase letters (a-z), numbers (0-9), and hyphens. Hyphens can’t appear at the start, end, or consecutively.
Default Actions & Routing
What action types can I configure for a listener?
You can configure two action types: fixed response (returns a specific status code like 404) or forward (routes traffic to one or more target groups).
How do I distribute traffic across multiple target groups?
Use the forwards action with multiple target groups, each with a weight property. For example, you can route 80% of traffic to one target group and 20% to another.
Ports & Protocols
What are the default port values for listeners?
If you don’t specify a port, HTTP listeners default to port 80 and HTTPS listeners default to port 443. You can specify any port from 1 to 65535.
What protocols are supported for VPC Lattice listeners?
VPC Lattice listeners support three protocols: HTTP, HTTPS, and TLS_PASSTHROUGH.
Immutability & Updates
What properties can't I change after creating a listener?
The name, port, and protocol properties are immutable. Changing any of these requires recreating the listener.
Can I update the default action after creating a listener?
Yes, the defaultAction property can be updated without recreating the listener.

Using a different cloud?

Explore networking guides for other cloud providers: