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 based on configured actions. This guide focuses on two capabilities: fixed response actions and target group forwarding with optional traffic weighting.

Listeners belong to VPC Lattice services and forward traffic to target groups containing instances, IPs, or Lambda functions. The examples are intentionally small. Combine them with your own services, target groups, and routing rules.

Return a fixed HTTP response without routing

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

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 a request arrives. A fixedResponse action returns the specified statusCode directly without forwarding to any backend. The protocol property determines the listener’s communication protocol; port defaults to 80 for HTTP and 443 for HTTPS if not specified.

Route traffic to a single target group

Most listeners forward incoming requests to a target group containing the actual workload handlers.

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 an existing target group. This configuration sends all traffic to one backend without splitting or weighting.

Split traffic across multiple target groups

Applications running canary deployments or A/B tests distribute traffic across multiple backend versions with percentage control.

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. Weights are relative: 80 and 20 result in an 80/20 split. VPC Lattice handles the distribution automatically based on these ratios, enabling gradual rollouts or testing scenarios.

Beyond these examples

These snippets focus on specific listener-level features: fixed responses and traffic forwarding, and weighted target group 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 entire service mesh.

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

  • Port configuration (defaults to 80 for HTTP, 443 for HTTPS)
  • TLS_PASSTHROUGH protocol support
  • Listener rules for path-based or header-based routing
  • 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
What protocols and ports are supported for VPC Lattice listeners?
Listeners support HTTP, HTTPS, or TLS_PASSTHROUGH protocols. Ports range from 1 to 65535, defaulting to 80 for HTTP and 443 for HTTPS if not specified.
Do I need to provide serviceArn or serviceIdentifier?
You must provide exactly one of these arguments to identify the VPC Lattice service. Choose either serviceArn or serviceIdentifier, but not both.
What types of default actions can I configure?
You can configure two action types: fixedResponse (returns a status code like 404) or forwards (routes traffic to one or more target groups).
How do I distribute traffic across multiple target groups with different weights?
Add multiple target groups to defaultAction.forwards.targetGroups, each with a weight value. For example, you can route 80% of traffic to one group and 20% to another.
Naming & Immutability
What properties can't I change after creating a listener?
The name, port, and protocol properties are immutable. Changing any of these will force replacement of the listener.
What are the naming requirements for listeners?
Listener names must be unique within a service and use only a-z, 0-9, and hyphens. Hyphens can’t be the first or last character, or appear consecutively.

Using a different cloud?

Explore networking guides for other cloud providers: