> ## Documentation Index
> Fetch the complete documentation index at: https://ngrok.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Forwarding Traffic to and Load Balancing Internal Endpoints with Cloud Endpoints

> How to use ngrok Cloud Endpoints to do round-robin load balancing.

This guide provides an example of using an ngrok Cloud Endpoint to route traffic between multiple internal endpoints.

## Core concepts

* [Cloud endpoints](/gateway/cloud-endpoints) are centrally managed endpoints in the cloud that can be used to route traffic to Agent Endpoints.
* [Internal endpoints](/gateway/internal-endpoints) are endpoints that are not publicly accessible and are only reachable from within your network by Cloud Endpoints via the forward action.
* **Load balancing** improves application performance and reduces load by distributing incoming traffic across servers. This leads to faster response times for user-facing applications.

## Prerequisites

To follow this guide, you will need a local computer with `ngrok` installed. [You can download ngrok here.](https://download.ngrok.com).

If you are going to be following along using the **ngrok CLI**, you will need:

* An [ngrok API key](https://dashboard.ngrok.com/api) configured on your [ngrok agent](/agent/#api-keys).

If you are going to be following along using **CURL**, you will need:

* An [ngrok API key](https://dashboard.ngrok.com/api) as an environment variable named `NGROK_API_KEY`.

## 1. Create an internal endpoint

Start by creating an internal endpoint, initiated from the agent.
The endpoints will be in HTTP for this guide, but you can also use TCP or TLS.

```bash theme={null}
ngrok http 80 \
    --url https://your-domain-name.internal
```

After running the above command, you should see an internal endpoint with an "online" status for your domain. This endpoint will route traffic to the app running at your local port 80.
You can set up any HTTP server to run on this port locally, and it the endpoint will internally route traffic to that server.

## 2. Create a domain

Next, create the domain that the Cloud Endpoint will reside on.
For the purpose of this guide, create an ngrok HTTP domain.

<Tabs>
  <Tab title="ngrok CLI">
    ```bash theme={null}
    ngrok api reserved-domains create \
        --domain ${NGROK_SUBDOMAIN}.ngrok.app
    ```

    * Replace or set `${NGROK_SUBDOMAIN}` as the subdomain you'd like to use for this guide.

    After running, you should see the following:

    ```json skip-validation theme={null}
    200 OK
    {
       "id":"rd_2MT5Bqt0UzU0mFQ0zr8m1UQWCfm",
       ...
    }
    ```
  </Tab>

  <Tab title="CURL">
    ```bash theme={null}
    curl \
        -X POST https://api.ngrok.com/reserved_domains \
        -H "Authorization: Bearer ${NGROK_API_KEY}" \
        -H "Content-Type: application/json" \
        -H "Ngrok-Version: 2" \
        -d @- <<BODY
        {
            "domain":"${NGROK_SUBDOMAIN}.ngrok.app",
        }
    BODY
    ```

    * Replace `NGROK_API_KEY` with your ngrok API key.
    * Replace NGROK\_SUBDOMAIN with the subdomain you'd like to use for this guide.

    Running this command should give you the following output:

    ```json skip-validation theme={null}
    200 OK
    {
       "id":"rd_2MT5Bqt0UzU0mFQ0zr8m1UQWCfm",
       ...
    }
    ```
  </Tab>

  <Tab title="ngrok Dashboard">
    You can reserve a subdomain via [ngrok dashboard](https://dashboard.ngrok.com/domains/new).
    After successfully reserving a domain, you should see it listed in the domains table.
  </Tab>
</Tabs>

When you have completed this step, you can move on to the next step.

## 3. Create a Traffic Policy for your Cloud Endpoint

Unlike Agent Endpoints in which Traffic Policies are optional,
Cloud Endpoints require a Traffic Policy so they know how to
handle incoming traffic. This guide will showcase one of the simplest
and most common use cases: forwarding traffic to other endpoints
(the internal endpoint created in Step 1) via the forward action.

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_http_request:
  - actions:
    - type: forward-internal
      config:
        url: https://your-domain-name.internal
  ```

  ```json policy.json theme={null}
  {
    "on_http_request": [
      {
        "actions": [
          {
            "type": "forward-internal",
            "config": {
              "url": "https://your-domain-name.internal"
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

## 4. Create an ngrok Cloud Endpoint

Now create an ngrok Cloud Endpoint that points to the
newly created internal endpoint. Cloud Endpoints can be created
via the API or ngrok dashboard.

<Tabs>
  <Tab title="API">
    We use the URL from Step 2 as the `url` value in the Traffic Policy, and the Traffic Policy from Step 3 as the `traffic-policy` value.
    The binding is set to public so anyone can access our Cloud Endpoint.

    ```bash theme={null}
    ngrok api endpoints create \
        --api-key YOUR_NGROK_API_KEY \
        --bindings public \
        --description "sample description" \
        --metadata sample-metadata \
        --url https://${NGROK_SUBDOMAIN}.ngrok.app
        --traffic-policy '{"on_http_request":[{"actions":[{"type":"forward-internal","config":{"url":"https://clep.internal","binding":"internal"}}]}]}'
    ```

    * Replace NGROK\_SUBDOMAIN with the value used in step 2.
  </Tab>

  <Tab title="ngrok Dashboard">
    Coming soon!
  </Tab>
</Tabs>

## 5. Load balancing with Endpoint Pools

Load balancing is simple with ngrok Endpoint Pools.
Start another agent with the same internal endpoint URL, and the traffic will be automatically load balanced between the two agents in the pool.

```bash theme={null}
ngrok http 80 \
	--url https://your-domain-name.internal
```

## Conclusion

You're done. You've successfully created a Cloud Endpoint that can be accessed from the URL you reserved: `${NGROK_SUBDOMAIN}.ngrok.app`
The Cloud Endpoint will refer to its Traffic Policy and forward traffic to the internal endpoint. The internal endpoint finally exposes the local port on which it was created on in Step 1.
