AWS ALB rules are surprisingly flexible, letting you route traffic not just by path, but by host, HTTP headers, query parameters, and even the source IP address.

Let’s say you have an ALB named my-app-alb in the us-east-1 region, and you want to route traffic based on a custom header. Your application expects a header X-Version: staging to hit a specific set of target groups.

Here’s how you’d set that up:

First, ensure you have your target groups ready. Let’s assume you have staging-tg and production-tg already configured and registered with instances.

Now, you’ll create a rule on your ALB’s listener. We’ll use the AWS CLI for this.

aws elbv2 create-rule \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-app-alb/1234567890abcdef/fedcba9876543210 \
    --conditions \
        '{"Field": "header", "Values": ["X-Version:staging"]}' \
    --priority 2 \
    --actions \
        '{"Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/staging-tg/a1b2c3d4e5f67890"}'

Let’s break this down:

  • --listener-arn: This is the ARN of the listener on your ALB. You can find this in the ALB console or by running aws elbv2 describe-listeners --load-balancer-arn <your-alb-arn>.
  • --conditions: This is where the magic happens.
    • "Field": "header": We’re specifying that we want to match based on an HTTP header.
    • "Values": ["X-Version:staging"]: This is the actual header and value we’re looking for. The ALB will only match if the incoming request has an X-Version header with the exact value staging. You can specify multiple values for a single header field, and the rule will match if any of them are present.
  • --priority: Rules are evaluated in order of priority. Lower numbers are evaluated first. We’re setting this to 2, assuming a default rule with a higher priority (like 1) already exists, or we’re placing this rule before a default rule.
  • --actions: This defines what happens when the rule matches.
    • "Type": "forward": We want to send the traffic to a target group.
    • "TargetGroupArn": The ARN of the target group to send the traffic to. In this case, it’s our staging-tg.

So, if a request comes in with X-Version: staging, it will be routed to staging-tg. If it has X-Version: production, it won’t match this rule. If it doesn’t have the X-Version header at all, it also won’t match.

You can also chain multiple conditions. For instance, to route based on a specific host and a header:

aws elbv2 create-rule \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-app-alb/1234567890abcdef/fedcba9876543210 \
    --conditions \
        '{"Field": "host-header", "Values": ["staging.example.com"]}' \
        '{"Field": "header", "Values": ["X-Version:staging"]}' \
    --priority 3 \
    --actions \
        '{"Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/staging-tg/a1b2c3d4e5f67890"}'

Here, the rule will only match if the incoming request is for staging.example.com AND has the X-Version: staging header. This allows for very granular traffic management.

The host-header condition is particularly useful for managing multiple domains or subdomains through a single ALB. You can have rules for api.example.com, www.example.com, and staging.example.com all pointing to different target groups, all on the same listener port.

Another powerful condition is path-pattern. This is what most people think of with routing:

aws elbv2 create-rule \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-app-alb/1234567890abcdef/fedcba9876543210 \
    --conditions \
        '{"Field": "path-pattern", "Values": ["/api/*"]}' \
    --priority 4 \
    --actions \
        '{"Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/api-tg/f0e9d8c7b6a54321"}'

This rule sends any traffic where the URL path starts with /api/ to the api-tg. The wildcard * is essential here. You can also use * at the beginning of a path, like */v1/*, but AWS ALB path matching is more specific than simple globbing; it matches the entire path against the pattern.

The source-ip condition allows you to restrict access to specific IP ranges, which can be useful for internal tools or whitelisting.

aws elbv2 create-rule \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-app-alb/1234567890abcdef/fedcba9876543210 \
    --conditions \
        '{"Field": "source-ip", "Values": ["192.168.1.0/24", "10.0.0.0/16"]}' \
    --priority 5 \
    --actions \
        '{"Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/internal-app-tg/1122334455667788"}'

This rule would only allow requests originating from the 192.168.1.0/24 or 10.0.0.0/16 subnets to be routed to internal-app-tg.

When you’re setting up rules, remember that the default rule (often with priority 1) is the catch-all. If no other rule matches, traffic goes to the default. You can also set the default action to be a fixed response or an redirect.

A common pitfall is rule priority. If you have a broad path rule like / with a low priority number (e.g., 1), it will match everything. Any more specific rules (like /api/* or /users/*) need a lower priority number to be evaluated first. For example, /api/* might be priority 2, and /users/* priority 3, with / being priority 4.

The exact behavior of path-pattern matching is important: it matches the entire path. So, /api/users would match /api/*, but /api would not. If you need to match specific segments, you might need multiple path-pattern conditions or rely on header/query parameter routing.

Once you’ve created rules, you can view them using:

aws elbv2 describe-rules --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-app-alb/1234567890abcdef/fedcba9876543210

This command will show you all the rules associated with that listener, including their conditions, priorities, and actions.

You can also modify existing rules, though it’s often simpler to delete and recreate them if the conditions or actions change significantly.

The interplay between host-headers, path-patterns, and other conditions allows for sophisticated traffic distribution strategies, such as blue/green deployments where you might route a small percentage of traffic to a new version based on a header, or canary releases by sending traffic to a new version only when a specific header is present.

When you combine conditions, the ALB treats them as an AND operation. All specified conditions for a rule must be met for that rule to trigger.

The next step after mastering basic routing rules is understanding how to implement weighted target groups, which allows you to send a percentage of traffic to different target groups for A/B testing or gradual rollouts without needing explicit header or path conditions.

Want structured learning?

Take the full Load-balancing course →