---
name: vpc-lb-layer-7-policies-rules
title: Policy-based load balancing
description: Both public and private application load balancers support layer 4 and layer 7 load balancing, where data traffic is distributed based on configured policies and rules. A policy defines the action to take, which means how the traffic is distributed, when the incoming request matches the rules that are associated with the policy.
last-updated: 2026-06-16
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/vpc?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# Policy-based load balancing
{: #layer-7-load-balancing}

Both public and private application load balancers support layer 4 and layer 7 load balancing, where data traffic is distributed based on configured policies and rules. A policy defines the action to take, which means how the traffic is distributed, when the incoming request matches the rules that are associated with the policy.

## Layer 7 policies
{: #layer-7-policy}

You can define policies for HTTP and HTTPS listeners. For each policy, you must define one or more rules. The policy is applied only when all its rules are matched.

You can attach more than one policy to a listener. In general, a policy with the lowest priority is evaluated first. Each policy must have a different priority.

If the incoming request does not match the rules for any policy, the system request redirects to the configured HTTPS redirect listener, if present. Otherwise, the system redirects the request to the default pool of the listener. The HTTPS redirect has a higher precedence over the default pool on an HTTP listener.

The following actions are supported for a layer 7 policy:

* **Reject** - The request is denied with a 403 response.
* **Redirect** - The request is redirected to a configured URL and response code.
* **Forward to pool** - The request is sent to a specific back-end pool.
* **Forward to listener** - The request is sent to a specific front-end listener.
* **HTTPS redirect** - The HTTP request redirects to an HTTPS listener.

## Policy properties
{: #layer-7-policy-properties}

Property  | Description
------------- | -------------
Name | The name of the policy. The name must be unique within the listener.
Action | The action to take when all policy rules match. The acceptable values are `reject`, `redirect`, `forward_to_pool`, `forward_to_listener`, and `https_redirect`.
Priority | Policies are evaluated based on ascending order of priority.
Priority | Policies are evaluated based on ascending order of priority.
URL | The URL to which the request is redirected, if the action is set to `redirect`. You must provide either a full URL or the parameters of a URI. When using a URL, all incoming traffic redirects to this URL. When using URI parameters, values from incoming traffic requests can be retained by using the incoming values of the parameters. The default values of the URI parameters are equal to their original incoming values. To retain the incoming values, provide them as `{protocol}`, `{port}`, `{host}`, `{path}`, and `{query}`. For example, if the host of the incoming request is `ibm.com`, then the default value is `{host}` equal to the incoming `ibm.com` value.
HTTP status code | Status code of the response returned by the application load balancer when the action is set to `redirect` or `https_redirect`. The acceptable values are: `301`, `302`, `303`, `307`, or `308`.
Target | If the action is set to `forward_to_pool`, the request is forwarded to the back-end pool of virtual server instances. Alternatively, if the action is set to `forward_to_listener`, the request is forwarded to a front-end listener of the same ALB.
Listener | The HTTPS listener to which the request is redirected, if the action is set to `https_redirect`.
URI | The relative URI to which the request is redirected, if the action is `https_redirect`. This property is optional.
{: caption="Description of policy properties" caption-side="bottom"}

## Layer 7 rules
{: #layer-7-rules}

A rule defines how a request is matched. Both URI-based routing and parameter-based routing are supported. The following five rule types are supported.
Type      |  Description
----------| -----------------------
`hostname` | The request matches the specified `hostname`, such as `api.my_company.com`.
`header`   | The request matches an HTTP `header` field and value, such as `Cookie: xxxx`.
`path`     | The request matches the `path` in the URL after the `hostname`, such as `/index.html`.
`query`    | The request matches the `query` string in the URL, for example `x=y`. The `query` string must be percent-encoded, and it is case-sensitive.
`body`     | The request `body` for the `POST` request is form-encoded. The request matches the body, for example `key=value`. It is case-sensitive.
`sni_hostname` | The server provided in the "server name indication" extension during TLS negotiation matches the specified SNI hostname.
{: caption="Layer 7 rules" caption-side="bottom"}

To match a request, a `condition` statement must be defined in a rule. The following four conditions are supported.

Condition |  Type of evaluation
----------------|---------------------
`contains`        |  Verifies whether the value extracted based on the `type` contains the string that is specified in the `value`.
`equals`        |  Verifies whether the value extracted based on the `type` is identical to the string specified in the `value`.
`matches_regex`           |  Matches the value extracted based on the `type` with the regular expression that is specified in the `value`.
`starts_with`           |  Verifies whether the value extracted based on the `type` starts with the string that is specified in the `value`.
{: caption="Condition statements defined in a rule" caption-side="bottom"}

## Rule properties
{: #layer-7-rule-properties}

This table describes layer 7 policy rule properties.

Property  | Description
------------- | -------------
`type` | Specifies the type of rule. The acceptable values are `hostname`, `header`, `path`, `query`, or `body`.
`condition` | Specifies the condition used to evaluate the rule. The supported values are `contains`, `equals`, or `matches_regex`.
`field` | Specifies the field name. This field is applicable only to the `header` `query` and `body` rule type and does not support regular expression and wildcard characters. For example, to match a cookie in the HTTP header, the field can be set to `cookie`. When the rule type is `query` and `body`, this field is optional. This property is not applicable to the `sni_hostname` rule type.
`value` | The string to be matched. This field does not support wildcard characters. Regular expressions are supported when the `condition` is set to `matches_regex`.
{: caption="Descriptions of rule properties" caption-side="bottom"}

**Notes**:

* If the rule type is `header`, the following characters are not allowed for `field` and `value`: `"(),/:;<=>?@[\]{}'`.
* If the rule type is `body`, the following characters are not allowed for `field` and `value`: `"'=,()&` and space.
* If the rule type is `query`, `field` and `value` must be a percent-encoded string.

## Examples: Creating policies and rules
{: #layer-7-examples-create-policy-and-rules}

The following layer 7 examples show how policies and rules are created and associated with a listener.

### Example 1: Create an HTTPS listener with redirect policies
{: #create-https-listener-redirect}

```bash
curl -H "Authorization: Bearer $iam_token" -X POST
"$vpc_api_endpoint/v1/load_balancers/$lbId/listeners" \
    -d '{
            "certificate_instance": {
                "crn": "crn:v1:bluemix:public:cloudcerts:us-south:a/1111111111111111111111111111:22222222-3333-4444-5555-666666666666:certificate:77777777777777777777777777777777"
            },
            "connection_limit": 2000,
            "port": 443,
            "protocol": "https",
            "policies": [
                {
                    "name": "hostname_header",
                    "action": "redirect",
                    "priority": 1,
                    "target": {
                        "url": "https://www.examples.com/",
                        "http_status_code": 307
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "header",
                            "field": "aheader",
                            "value": "avalue"
                        },
                        {
                            "condition": "equals",
                            "type": "hostname",
                            "value": "abc.com"
                        }
                    ]
                },
                {
                    "name": "header_cookie",
                    "action": "redirect",
                    "priority": 5,
                    "target": {
                        "url": "https://www.mycookies.com/",
                        "http_status_code": 302
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "header",
                            "field": "aheader",
                            "value": "avalue"
                        },
                        {
                            "condition": "equals",
                            "type": "header",
                            "field": "cookie",
                            "value": "flavor=oatmeal"
                        }
                    ]
                },
                {
                    "name": "path_hostname",
                    "action": "redirect",
                    "priority": 10,
                    "target": {
                        "url": "https://www.myexamples.com/",
                        "http_status_code": 301
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "hostname",
                            "value": "abc"
                        },
                        {
                            "condition": "equals",
                            "value": "/test",
                            "type": "path"
                          }
                    ]
                },
                {
                    "name": "uri_redirect",
                    "action": "redirect",
                    "priority": 10,
                    "target": {
                        "url": "https://{host}:8080/{path}?{query}",
                        "http_status_code": 301
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "hostname",
                            "value": "pqr"
                        }
                    ]
                }
            ]
        }'
```
{: codeblock}

### Example 2: Create policies to forward requests to pools and associate it with an existing listener
{: #create-policies-forward-requests}

```bash
curl -H "Authorization: Bearer $iam_token" -X POST
"$vpc_api_endpoint/v1/load_balancers/$lbId/listeners/$listenerId/policies" \
    -d '{
            "policies": [
                {
                    "action": "forward",
                    "priority": 1,
                    "target": {
                        "id": "7df616da-4dd6-43d3-881d-801ae29e29fe"
                    },
                    "rules": [
                        {
                            "condition": "equals",
                            "type": "header",
                            "field": "cookie",
                            "value": "flavor=oatmeal"
                        }
                    ]
                },
                {
                    "action": "forward",
                    "priority": 5,
                    "target": {
                        "id": "0738-8061c411-0d50-4c79-b475-102666796434"
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "header",
                            "field": "aheader",
                            "value": "avalue"
                        }
                    ]
                },
                {
                    "action": "forward",
                    "priority": 10,
                    "target": {
                        "id": "0738-62914e09-3928-4d89-b7f7-1bb7a6d7fe85"
                    },
                    "rules": [
                        {
                            "condition": "matches_regex",
                            "type": "hostname",
                            "value": "abc[a-z]*.com"
                        }
                    ]
                },
                {
                    "action": "forward",
                    "priority": 6,
                    "target": {
                        "id": "0738-62914e09-3928-4d89-b7f7-1bb7a6d7fe85"
                    },
                    "rules": [
                        {
                            "condition": "equals",
                            "type": "path",
                            "value": "/test/testtest"
                        }
                    ]
                }
            ]
        }'
```
{: codeblock}

### Example 3: Create an HTTP listener with https redirect policies
{: #create-http-listener-https-redirect}

```bash
curl -H "Authorization: Bearer $iam_token" -X POST
"$vpc_api_endpoint/v1/load_balancers/$lbId/listeners" \
    -d '{
            "connection_limit": 2000,
            "port": 80,
            "protocol": "http",
            "policies": [
                {
                    "name": "hostname_header",
                    "action": "https_redirect",
                    "priority": 1,
                    "target": {
                        "listener": {
                            "id": "0134-d578be10-31e3-46b3-8513-79babb852319"
                        },
                        "http_status_code": 307
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "header",
                            "field": "aheader",
                            "value": "avalue"
                        },
                        {
                            "condition": "equals",
                            "type": "hostname",
                            "value": "abc.com"
                        }
                    ]
                },
                {
                    "name": "header_cookie",
                    "action": "https_redirect",
                    "priority": 2,
                    "target": {
                        "listener": {
                            "id": "0456-a578be10-31e3-46b3-8513-79babb852398"
                        },
                        "http_status_code": 302
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "header",
                            "field": "aheader",
                            "value": "avalue"
                        },
                        {
                            "condition": "equals",
                            "type": "header",
                            "field": "cookie",
                            "value": "flavor=oatmeal"
                        }
                    ]
                },
                {
                    "name": "path_hostname",
                    "action": "https_redirect",
                    "priority": 5,
                    "target": {
                        "listener": {
                            "id": "0386-d898be10-21e3-66b3-9513-69babb852390"
                        },
                        "http_status_code": 301,
                        "uri": "/test/sample"
                    },
                    "rules": [
                        {
                            "condition": "contains",
                            "type": "hostname",
                            "value": "abc"
                        },
                        {
                            "condition": "equals",
                            "value": "/test",
                            "type": "path"
                          }
                    ]
                }
            ]
        }'
```
{: codeblock}

## Layer 4 policies
{: #layer-4-policy}

You can define policies for TCP listeners. For each policy, you must define one or more rules. Similar to layer 7 policies, a layer 4 policy is applied with the lowest priority first and only when all of its designated rules are matched.

If the incoming request does not match the rules for any policy, the client may get an SSL error.
{: note}

The following actions are supported for layer 4 policies:

   * **Forward To pool** - The request is sent to a specific back-end pool.
   * **Forward To listener** - The request is sent to a specific front-end listener.

## Layer 4 rules
{: #layer-4-rules}

A layer 4 rule defines how requests are matched, the same as a layer 7 rule. However, only the `sni_hostname` type is supported, where `field` is not applicable and the `condition` and `value` properties are the same as for layer 7 rules.

The "SNI Hostname" rule only works with a TCP Listener.
{: note}

SNI in an IBM Cloud ALB is attached to the listener and lets you route traffic to different backend pools based on the hostname. Within a pool, traffic is always load-balanced across all members using the chosen algorithm (round-robin, least connections, etc). You cannot use SNI to pick a specific member inside a pool.

If you are using a backend pool with Protocol HTTP or HTTPs, then the ALB will not set the SNI when forwarding the client request to the backend pool. This is because the ALB only uses the SNI to make a forwarding decision (if layer 7 rules are configured), and the ALB does a separate TLS handshake with the backend (which is different from the consumer's handshake).

If you are using TCP protocol for the backend, instead of HTTP/HTTPs, then the ALB will set the SNI sent by the consumer. This is because the TLS handshake will be between the consumer and the backend directly, rather than between the ALB and the backend.

Use one of the following workarounds if you use HTTP/HTTPS Listener with an SNI:

1. Use a wildcard certificate on a virtual host. Then configure only a single host name on separate backend ports. For example, if you want per hostname routing to individual servers, you may create separate pools for each hostname and use the SNI to route to the correct pool.
1. Use TCP mode for the backend protocol instead of HTTPs. TCP mode will forward SNI correctly, and still allow for load balancing based on SNI hostname rules if you configure it.

### Example: Create a TCP listener with the `sni_hostname` rule
{: #layer4-example-1}

```bash
curl -H "Authorization: Bearer $iam_token" -X POST
"$vpc_api_endpoint/v1/load_balancers/$lbId/listeners"     -d '{
            "connection_limit": 2000,
            "port": 443,
            "protocol": "tcp",
            "policies": [
                {
                    "action": "forward_to_listener",
                    "name": "listener-forward-policy",
                    "priority": 4,
                    "rules": [
                      {
                        "condition": "equals",
                        "type": "sni_hostname",
                        "value": "www.example.com"
                      }
                    ],
                    "target": {
                      "id": "r006-20275400-825e-4d9b-8177-076fdb4134cc"
                    }
                }
            ]
        }'
```
{: codeblock}