Configure AWS App Mesh Routes

The aws:appmesh/route:Route resource, part of the Pulumi AWS provider, defines routing rules within an App Mesh virtual router: how traffic is matched, distributed across virtual nodes, and retried on failure. This guide focuses on three capabilities: HTTP and TCP traffic distribution, header-based request filtering, and automatic retry policies.

Routes belong to virtual routers and direct traffic to virtual nodes within a service mesh. The examples are intentionally small. Combine them with your own mesh, virtual routers, and virtual nodes.

Split HTTP traffic across virtual nodes

Service meshes often route traffic to multiple backend versions simultaneously, enabling canary deployments where most traffic goes to a stable version while a small percentage tests new code.

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

const serviceb = new aws.appmesh.Route("serviceb", {
    name: "serviceB-route",
    meshName: simple.id,
    virtualRouterName: servicebAwsAppmeshVirtualRouter.name,
    spec: {
        httpRoute: {
            match: {
                prefix: "/",
            },
            action: {
                weightedTargets: [
                    {
                        virtualNode: serviceb1.name,
                        weight: 90,
                    },
                    {
                        virtualNode: serviceb2.name,
                        weight: 10,
                    },
                ],
            },
        },
    },
});
import pulumi
import pulumi_aws as aws

serviceb = aws.appmesh.Route("serviceb",
    name="serviceB-route",
    mesh_name=simple["id"],
    virtual_router_name=serviceb_aws_appmesh_virtual_router["name"],
    spec={
        "http_route": {
            "match": {
                "prefix": "/",
            },
            "action": {
                "weighted_targets": [
                    {
                        "virtual_node": serviceb1["name"],
                        "weight": 90,
                    },
                    {
                        "virtual_node": serviceb2["name"],
                        "weight": 10,
                    },
                ],
            },
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := appmesh.NewRoute(ctx, "serviceb", &appmesh.RouteArgs{
			Name:              pulumi.String("serviceB-route"),
			MeshName:          pulumi.Any(simple.Id),
			VirtualRouterName: pulumi.Any(servicebAwsAppmeshVirtualRouter.Name),
			Spec: &appmesh.RouteSpecArgs{
				HttpRoute: &appmesh.RouteSpecHttpRouteArgs{
					Match: &appmesh.RouteSpecHttpRouteMatchArgs{
						Prefix: pulumi.String("/"),
					},
					Action: &appmesh.RouteSpecHttpRouteActionArgs{
						WeightedTargets: appmesh.RouteSpecHttpRouteActionWeightedTargetArray{
							&appmesh.RouteSpecHttpRouteActionWeightedTargetArgs{
								VirtualNode: pulumi.Any(serviceb1.Name),
								Weight:      pulumi.Int(90),
							},
							&appmesh.RouteSpecHttpRouteActionWeightedTargetArgs{
								VirtualNode: pulumi.Any(serviceb2.Name),
								Weight:      pulumi.Int(10),
							},
						},
					},
				},
			},
		})
		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 serviceb = new Aws.AppMesh.Route("serviceb", new()
    {
        Name = "serviceB-route",
        MeshName = simple.Id,
        VirtualRouterName = servicebAwsAppmeshVirtualRouter.Name,
        Spec = new Aws.AppMesh.Inputs.RouteSpecArgs
        {
            HttpRoute = new Aws.AppMesh.Inputs.RouteSpecHttpRouteArgs
            {
                Match = new Aws.AppMesh.Inputs.RouteSpecHttpRouteMatchArgs
                {
                    Prefix = "/",
                },
                Action = new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionArgs
                {
                    WeightedTargets = new[]
                    {
                        new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionWeightedTargetArgs
                        {
                            VirtualNode = serviceb1.Name,
                            Weight = 90,
                        },
                        new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionWeightedTargetArgs
                        {
                            VirtualNode = serviceb2.Name,
                            Weight = 10,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appmesh.Route;
import com.pulumi.aws.appmesh.RouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteMatchArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteActionArgs;
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 serviceb = new Route("serviceb", RouteArgs.builder()
            .name("serviceB-route")
            .meshName(simple.id())
            .virtualRouterName(servicebAwsAppmeshVirtualRouter.name())
            .spec(RouteSpecArgs.builder()
                .httpRoute(RouteSpecHttpRouteArgs.builder()
                    .match(RouteSpecHttpRouteMatchArgs.builder()
                        .prefix("/")
                        .build())
                    .action(RouteSpecHttpRouteActionArgs.builder()
                        .weightedTargets(                        
                            RouteSpecHttpRouteActionWeightedTargetArgs.builder()
                                .virtualNode(serviceb1.name())
                                .weight(90)
                                .build(),
                            RouteSpecHttpRouteActionWeightedTargetArgs.builder()
                                .virtualNode(serviceb2.name())
                                .weight(10)
                                .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  serviceb:
    type: aws:appmesh:Route
    properties:
      name: serviceB-route
      meshName: ${simple.id}
      virtualRouterName: ${servicebAwsAppmeshVirtualRouter.name}
      spec:
        httpRoute:
          match:
            prefix: /
          action:
            weightedTargets:
              - virtualNode: ${serviceb1.name}
                weight: 90
              - virtualNode: ${serviceb2.name}
                weight: 10

When a request matches the prefix, App Mesh distributes it across the weighted targets. Here, 90% of requests go to serviceb1 and 10% to serviceb2. The match block defines which requests this route handles; the action block specifies where they go and in what proportion.

Route requests based on HTTP headers and method

Applications sometimes need to route requests differently based on headers, HTTP methods, or URL schemes, directing specific client types or request patterns to dedicated backends.

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

const serviceb = new aws.appmesh.Route("serviceb", {
    name: "serviceB-route",
    meshName: simple.id,
    virtualRouterName: servicebAwsAppmeshVirtualRouter.name,
    spec: {
        httpRoute: {
            match: {
                method: "POST",
                prefix: "/",
                scheme: "https",
                headers: [{
                    name: "clientRequestId",
                    match: {
                        prefix: "123",
                    },
                }],
            },
            action: {
                weightedTargets: [{
                    virtualNode: servicebAwsAppmeshVirtualNode.name,
                    weight: 100,
                }],
            },
        },
    },
});
import pulumi
import pulumi_aws as aws

serviceb = aws.appmesh.Route("serviceb",
    name="serviceB-route",
    mesh_name=simple["id"],
    virtual_router_name=serviceb_aws_appmesh_virtual_router["name"],
    spec={
        "http_route": {
            "match": {
                "method": "POST",
                "prefix": "/",
                "scheme": "https",
                "headers": [{
                    "name": "clientRequestId",
                    "match": {
                        "prefix": "123",
                    },
                }],
            },
            "action": {
                "weighted_targets": [{
                    "virtual_node": serviceb_aws_appmesh_virtual_node["name"],
                    "weight": 100,
                }],
            },
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := appmesh.NewRoute(ctx, "serviceb", &appmesh.RouteArgs{
			Name:              pulumi.String("serviceB-route"),
			MeshName:          pulumi.Any(simple.Id),
			VirtualRouterName: pulumi.Any(servicebAwsAppmeshVirtualRouter.Name),
			Spec: &appmesh.RouteSpecArgs{
				HttpRoute: &appmesh.RouteSpecHttpRouteArgs{
					Match: &appmesh.RouteSpecHttpRouteMatchArgs{
						Method: pulumi.String("POST"),
						Prefix: pulumi.String("/"),
						Scheme: pulumi.String("https"),
						Headers: appmesh.RouteSpecHttpRouteMatchHeaderArray{
							&appmesh.RouteSpecHttpRouteMatchHeaderArgs{
								Name: pulumi.String("clientRequestId"),
								Match: &appmesh.RouteSpecHttpRouteMatchHeaderMatchArgs{
									Prefix: pulumi.String("123"),
								},
							},
						},
					},
					Action: &appmesh.RouteSpecHttpRouteActionArgs{
						WeightedTargets: appmesh.RouteSpecHttpRouteActionWeightedTargetArray{
							&appmesh.RouteSpecHttpRouteActionWeightedTargetArgs{
								VirtualNode: pulumi.Any(servicebAwsAppmeshVirtualNode.Name),
								Weight:      pulumi.Int(100),
							},
						},
					},
				},
			},
		})
		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 serviceb = new Aws.AppMesh.Route("serviceb", new()
    {
        Name = "serviceB-route",
        MeshName = simple.Id,
        VirtualRouterName = servicebAwsAppmeshVirtualRouter.Name,
        Spec = new Aws.AppMesh.Inputs.RouteSpecArgs
        {
            HttpRoute = new Aws.AppMesh.Inputs.RouteSpecHttpRouteArgs
            {
                Match = new Aws.AppMesh.Inputs.RouteSpecHttpRouteMatchArgs
                {
                    Method = "POST",
                    Prefix = "/",
                    Scheme = "https",
                    Headers = new[]
                    {
                        new Aws.AppMesh.Inputs.RouteSpecHttpRouteMatchHeaderArgs
                        {
                            Name = "clientRequestId",
                            Match = new Aws.AppMesh.Inputs.RouteSpecHttpRouteMatchHeaderMatchArgs
                            {
                                Prefix = "123",
                            },
                        },
                    },
                },
                Action = new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionArgs
                {
                    WeightedTargets = new[]
                    {
                        new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionWeightedTargetArgs
                        {
                            VirtualNode = servicebAwsAppmeshVirtualNode.Name,
                            Weight = 100,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appmesh.Route;
import com.pulumi.aws.appmesh.RouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteMatchArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteActionArgs;
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 serviceb = new Route("serviceb", RouteArgs.builder()
            .name("serviceB-route")
            .meshName(simple.id())
            .virtualRouterName(servicebAwsAppmeshVirtualRouter.name())
            .spec(RouteSpecArgs.builder()
                .httpRoute(RouteSpecHttpRouteArgs.builder()
                    .match(RouteSpecHttpRouteMatchArgs.builder()
                        .method("POST")
                        .prefix("/")
                        .scheme("https")
                        .headers(RouteSpecHttpRouteMatchHeaderArgs.builder()
                            .name("clientRequestId")
                            .match(RouteSpecHttpRouteMatchHeaderMatchArgs.builder()
                                .prefix("123")
                                .build())
                            .build())
                        .build())
                    .action(RouteSpecHttpRouteActionArgs.builder()
                        .weightedTargets(RouteSpecHttpRouteActionWeightedTargetArgs.builder()
                            .virtualNode(servicebAwsAppmeshVirtualNode.name())
                            .weight(100)
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  serviceb:
    type: aws:appmesh:Route
    properties:
      name: serviceB-route
      meshName: ${simple.id}
      virtualRouterName: ${servicebAwsAppmeshVirtualRouter.name}
      spec:
        httpRoute:
          match:
            method: POST
            prefix: /
            scheme: https
            headers:
              - name: clientRequestId
                match:
                  prefix: '123'
          action:
            weightedTargets:
              - virtualNode: ${servicebAwsAppmeshVirtualNode.name}
                weight: 100

The match block filters incoming requests by method (POST), scheme (https), and header values. Only requests with a clientRequestId header starting with “123” reach this route. The headers array supports prefix, exact, range, and regex matching for flexible filtering.

Add automatic retries for transient failures

Distributed systems encounter transient failures like network timeouts or temporary service unavailability. Retry policies automatically reattempt failed requests without requiring application-level retry logic.

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

const serviceb = new aws.appmesh.Route("serviceb", {
    name: "serviceB-route",
    meshName: simple.id,
    virtualRouterName: servicebAwsAppmeshVirtualRouter.name,
    spec: {
        httpRoute: {
            match: {
                prefix: "/",
            },
            retryPolicy: {
                httpRetryEvents: ["server-error"],
                maxRetries: 1,
                perRetryTimeout: {
                    unit: "s",
                    value: 15,
                },
            },
            action: {
                weightedTargets: [{
                    virtualNode: servicebAwsAppmeshVirtualNode.name,
                    weight: 100,
                }],
            },
        },
    },
});
import pulumi
import pulumi_aws as aws

serviceb = aws.appmesh.Route("serviceb",
    name="serviceB-route",
    mesh_name=simple["id"],
    virtual_router_name=serviceb_aws_appmesh_virtual_router["name"],
    spec={
        "http_route": {
            "match": {
                "prefix": "/",
            },
            "retry_policy": {
                "http_retry_events": ["server-error"],
                "max_retries": 1,
                "per_retry_timeout": {
                    "unit": "s",
                    "value": 15,
                },
            },
            "action": {
                "weighted_targets": [{
                    "virtual_node": serviceb_aws_appmesh_virtual_node["name"],
                    "weight": 100,
                }],
            },
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := appmesh.NewRoute(ctx, "serviceb", &appmesh.RouteArgs{
			Name:              pulumi.String("serviceB-route"),
			MeshName:          pulumi.Any(simple.Id),
			VirtualRouterName: pulumi.Any(servicebAwsAppmeshVirtualRouter.Name),
			Spec: &appmesh.RouteSpecArgs{
				HttpRoute: &appmesh.RouteSpecHttpRouteArgs{
					Match: &appmesh.RouteSpecHttpRouteMatchArgs{
						Prefix: pulumi.String("/"),
					},
					RetryPolicy: &appmesh.RouteSpecHttpRouteRetryPolicyArgs{
						HttpRetryEvents: pulumi.StringArray{
							pulumi.String("server-error"),
						},
						MaxRetries: pulumi.Int(1),
						PerRetryTimeout: &appmesh.RouteSpecHttpRouteRetryPolicyPerRetryTimeoutArgs{
							Unit:  pulumi.String("s"),
							Value: pulumi.Int(15),
						},
					},
					Action: &appmesh.RouteSpecHttpRouteActionArgs{
						WeightedTargets: appmesh.RouteSpecHttpRouteActionWeightedTargetArray{
							&appmesh.RouteSpecHttpRouteActionWeightedTargetArgs{
								VirtualNode: pulumi.Any(servicebAwsAppmeshVirtualNode.Name),
								Weight:      pulumi.Int(100),
							},
						},
					},
				},
			},
		})
		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 serviceb = new Aws.AppMesh.Route("serviceb", new()
    {
        Name = "serviceB-route",
        MeshName = simple.Id,
        VirtualRouterName = servicebAwsAppmeshVirtualRouter.Name,
        Spec = new Aws.AppMesh.Inputs.RouteSpecArgs
        {
            HttpRoute = new Aws.AppMesh.Inputs.RouteSpecHttpRouteArgs
            {
                Match = new Aws.AppMesh.Inputs.RouteSpecHttpRouteMatchArgs
                {
                    Prefix = "/",
                },
                RetryPolicy = new Aws.AppMesh.Inputs.RouteSpecHttpRouteRetryPolicyArgs
                {
                    HttpRetryEvents = new[]
                    {
                        "server-error",
                    },
                    MaxRetries = 1,
                    PerRetryTimeout = new Aws.AppMesh.Inputs.RouteSpecHttpRouteRetryPolicyPerRetryTimeoutArgs
                    {
                        Unit = "s",
                        Value = 15,
                    },
                },
                Action = new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionArgs
                {
                    WeightedTargets = new[]
                    {
                        new Aws.AppMesh.Inputs.RouteSpecHttpRouteActionWeightedTargetArgs
                        {
                            VirtualNode = servicebAwsAppmeshVirtualNode.Name,
                            Weight = 100,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appmesh.Route;
import com.pulumi.aws.appmesh.RouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteMatchArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteRetryPolicyArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteRetryPolicyPerRetryTimeoutArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecHttpRouteActionArgs;
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 serviceb = new Route("serviceb", RouteArgs.builder()
            .name("serviceB-route")
            .meshName(simple.id())
            .virtualRouterName(servicebAwsAppmeshVirtualRouter.name())
            .spec(RouteSpecArgs.builder()
                .httpRoute(RouteSpecHttpRouteArgs.builder()
                    .match(RouteSpecHttpRouteMatchArgs.builder()
                        .prefix("/")
                        .build())
                    .retryPolicy(RouteSpecHttpRouteRetryPolicyArgs.builder()
                        .httpRetryEvents("server-error")
                        .maxRetries(1)
                        .perRetryTimeout(RouteSpecHttpRouteRetryPolicyPerRetryTimeoutArgs.builder()
                            .unit("s")
                            .value(15)
                            .build())
                        .build())
                    .action(RouteSpecHttpRouteActionArgs.builder()
                        .weightedTargets(RouteSpecHttpRouteActionWeightedTargetArgs.builder()
                            .virtualNode(servicebAwsAppmeshVirtualNode.name())
                            .weight(100)
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  serviceb:
    type: aws:appmesh:Route
    properties:
      name: serviceB-route
      meshName: ${simple.id}
      virtualRouterName: ${servicebAwsAppmeshVirtualRouter.name}
      spec:
        httpRoute:
          match:
            prefix: /
          retryPolicy:
            httpRetryEvents:
              - server-error
            maxRetries: 1
            perRetryTimeout:
              unit: s
              value: 15
          action:
            weightedTargets:
              - virtualNode: ${servicebAwsAppmeshVirtualNode.name}
                weight: 100

The retryPolicy block configures automatic retries when App Mesh detects server errors. The httpRetryEvents property lists which error types trigger retries; maxRetries caps the number of attempts; perRetryTimeout sets how long to wait for each attempt. This moves retry logic from application code into the mesh infrastructure.

Route TCP traffic to virtual nodes

Non-HTTP protocols like databases or custom TCP services need routing rules that operate at the transport layer without inspecting application-level headers.

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

const serviceb = new aws.appmesh.Route("serviceb", {
    name: "serviceB-route",
    meshName: simple.id,
    virtualRouterName: servicebAwsAppmeshVirtualRouter.name,
    spec: {
        tcpRoute: {
            action: {
                weightedTargets: [{
                    virtualNode: serviceb1.name,
                    weight: 100,
                }],
            },
        },
    },
});
import pulumi
import pulumi_aws as aws

serviceb = aws.appmesh.Route("serviceb",
    name="serviceB-route",
    mesh_name=simple["id"],
    virtual_router_name=serviceb_aws_appmesh_virtual_router["name"],
    spec={
        "tcp_route": {
            "action": {
                "weighted_targets": [{
                    "virtual_node": serviceb1["name"],
                    "weight": 100,
                }],
            },
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := appmesh.NewRoute(ctx, "serviceb", &appmesh.RouteArgs{
			Name:              pulumi.String("serviceB-route"),
			MeshName:          pulumi.Any(simple.Id),
			VirtualRouterName: pulumi.Any(servicebAwsAppmeshVirtualRouter.Name),
			Spec: &appmesh.RouteSpecArgs{
				TcpRoute: &appmesh.RouteSpecTcpRouteArgs{
					Action: &appmesh.RouteSpecTcpRouteActionArgs{
						WeightedTargets: appmesh.RouteSpecTcpRouteActionWeightedTargetArray{
							&appmesh.RouteSpecTcpRouteActionWeightedTargetArgs{
								VirtualNode: pulumi.Any(serviceb1.Name),
								Weight:      pulumi.Int(100),
							},
						},
					},
				},
			},
		})
		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 serviceb = new Aws.AppMesh.Route("serviceb", new()
    {
        Name = "serviceB-route",
        MeshName = simple.Id,
        VirtualRouterName = servicebAwsAppmeshVirtualRouter.Name,
        Spec = new Aws.AppMesh.Inputs.RouteSpecArgs
        {
            TcpRoute = new Aws.AppMesh.Inputs.RouteSpecTcpRouteArgs
            {
                Action = new Aws.AppMesh.Inputs.RouteSpecTcpRouteActionArgs
                {
                    WeightedTargets = new[]
                    {
                        new Aws.AppMesh.Inputs.RouteSpecTcpRouteActionWeightedTargetArgs
                        {
                            VirtualNode = serviceb1.Name,
                            Weight = 100,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appmesh.Route;
import com.pulumi.aws.appmesh.RouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecTcpRouteArgs;
import com.pulumi.aws.appmesh.inputs.RouteSpecTcpRouteActionArgs;
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 serviceb = new Route("serviceb", RouteArgs.builder()
            .name("serviceB-route")
            .meshName(simple.id())
            .virtualRouterName(servicebAwsAppmeshVirtualRouter.name())
            .spec(RouteSpecArgs.builder()
                .tcpRoute(RouteSpecTcpRouteArgs.builder()
                    .action(RouteSpecTcpRouteActionArgs.builder()
                        .weightedTargets(RouteSpecTcpRouteActionWeightedTargetArgs.builder()
                            .virtualNode(serviceb1.name())
                            .weight(100)
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  serviceb:
    type: aws:appmesh:Route
    properties:
      name: serviceB-route
      meshName: ${simple.id}
      virtualRouterName: ${servicebAwsAppmeshVirtualRouter.name}
      spec:
        tcpRoute:
          action:
            weightedTargets:
              - virtualNode: ${serviceb1.name}
                weight: 100

TCP routes use tcpRoute instead of httpRoute and omit the match block since TCP routing doesn’t inspect request content. The action block still supports weighted targets for distributing connections across backends.

Beyond these examples

These snippets focus on specific route-level features: HTTP and TCP routing, weighted traffic distribution, and header-based filtering and retry policies. They’re intentionally minimal rather than full service mesh configurations.

The examples reference pre-existing infrastructure such as App Mesh service meshes, virtual routers, and virtual nodes. They focus on configuring the route rather than provisioning the surrounding mesh components.

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

  • gRPC routing (grpcRoute)
  • Timeout configuration (timeout blocks)
  • Priority-based routing
  • Connection pool settings

These omissions are intentional: the goal is to illustrate how each route feature is wired, not provide drop-in mesh modules. See the App Mesh Route resource reference for all available configuration options.

Let's configure AWS App Mesh Routes

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Route Configuration & Types
What properties can't I change after creating a route?
The meshName, name, and virtualRouterName properties are immutable and will force resource replacement if changed.
What's the difference between HTTP and TCP routes?
HTTP routes support advanced matching on headers, methods, paths, and schemes, plus retry policies. TCP routes only support weighted target distribution without matching criteria.
What are the naming requirements for App Mesh routes?
Route names, mesh names, and virtual router names must be between 1 and 255 characters in length.
Traffic Management
How do I split traffic between different virtual nodes?
Use weightedTargets in the route action with weight values for each virtual node. For example, weights of 90 and 10 create a 90/10 traffic split for canary deployments.
Do the weight values need to sum to 100?
No, weights are proportional. Values of 90 and 10 produce the same 90/10 split as 9 and 1.
Advanced HTTP Routing
How do I route traffic based on HTTP headers or methods?
Configure the match block with headers, method, scheme, and prefix properties. For example, you can route POST requests with specific header values to designated virtual nodes.
How do I configure automatic retries for failed requests?
Add a retryPolicy to your HTTP route specifying httpRetryEvents (like “server-error”), maxRetries, and perRetryTimeout with unit and value.
What retry events can I configure for HTTP routes?
The example shows “server-error” as an httpRetryEvents value. Configure maxRetries and perRetryTimeout to control retry behavior.
Resource Management
How do I import an existing App Mesh route?
Use the format mesh_name/virtual_router_name/route_name, for example: pulumi import aws:appmesh/route:Route serviceb simpleapp/serviceB/serviceB-route

Using a different cloud?

Explore networking guides for other cloud providers: