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 incoming requests map to backend virtual nodes based on protocol, path, headers, and weights. This guide focuses on four capabilities: HTTP traffic splitting with weighted targets, request matching on headers and methods, automatic retry policies, and TCP routing for non-HTTP protocols.

Routes belong to virtual routers and reference virtual nodes as traffic destinations. The mesh, router, and nodes must exist before creating routes. The examples are intentionally small. Combine them with your own mesh topology and service definitions.

Split HTTP traffic across virtual nodes

Service meshes route traffic between versions or instances to enable gradual rollouts and A/B testing.

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

The httpRoute block defines how requests are distributed. The match.prefix property specifies which URL paths this route handles; “/” matches all requests. The weightedTargets array splits traffic across virtual nodes: 90% to serviceb1, 10% to serviceb2. App Mesh uses these weights to probabilistically route each request.

Route requests based on headers and method

Applications often route requests differently based on HTTP headers, methods, or schemes to implement feature flags or client-specific behavior.

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 requests by multiple criteria: method restricts to POST, scheme requires HTTPS, and headers matches requests with a clientRequestId header starting with “123”. Only requests matching all criteria follow this route. This extends basic HTTP routing by adding request attribute matching.

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. The httpRetryEvents property lists conditions that trigger retries; “server-error” covers 5xx responses. The maxRetries property limits retry attempts, and perRetryTimeout sets how long to wait for each attempt. This adds resilience to basic HTTP routing by handling transient failures transparently.

Route TCP traffic to virtual nodes

Non-HTTP services like databases or custom protocols require TCP-level routing without HTTP-specific features.

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

The tcpRoute block routes TCP connections without HTTP semantics. Unlike HTTP routes, TCP routes have no match criteria or retry policies; they simply distribute connections across weighted targets. Use this for database connections, custom binary protocols, or any non-HTTP service.

Beyond these examples

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

The examples reference pre-existing infrastructure such as App Mesh service meshes, virtual routers, and virtual nodes (backend targets). They focus on configuring the route rather than provisioning the entire mesh topology.

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

  • Timeout configuration (timeout blocks)
  • gRPC routing (grpcRoute)
  • 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

Resource Management
What properties can't I change after creating a route?
The meshName, meshOwner, name, and virtualRouterName properties are immutable and will force resource replacement if changed.
How do I import an existing App Mesh route?
Use the format meshName/virtualRouterName/routeName in your import command, for example: simpleapp/serviceB/serviceB-route.
Route Types & Traffic Distribution
What's the difference between HTTP and TCP routing?
HTTP routes support advanced features like header matching, method/scheme filtering, and retry policies. TCP routes only support weighted target distribution without additional matching criteria.
How do I split traffic between multiple virtual nodes?
Configure weightedTargets in the action block with weight values for each virtual node. For example, weights of 90 and 10 create a 90/10 traffic split.
HTTP Routing Features
How do I route traffic based on HTTP headers?
Add a headers array to the match block with header name and match criteria (prefix, exact, regex, range, or suffix matching).
Can I configure automatic retries for failed requests?
Yes, add a retryPolicy to your httpRoute specifying httpRetryEvents, maxRetries, and perRetryTimeout values.
What HTTP matching criteria can I use besides headers?
You can match on method (e.g., POST), prefix (URL path), and scheme (http or https) in the match block.

Using a different cloud?

Explore networking guides for other cloud providers: