> ## Documentation Index
> Fetch the complete documentation index at: https://gcore-doc-1256a.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Create and configure a load balancer

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).filter(c => c && c.props && c.props.id);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    A Load Balancer is a tool used to sort incoming requests across your Virtual Machines to improve your infrastructure's fault tolerance.

    ## Step 1. Initiate Load Balancer creation

    Go to your project, navigate to the "Load Balancers" in the "Networking" section and click **Create Load Balancer**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-1-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=e27b116d27f44ddb3581b0a0373924c1" alt="Initiate the process of Load Balancer creation" width="1400" height="900" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-1-lb.png" />
    </Frame>

    The new page opens. Perform the remaining steps there.

    ## Step 2. Set the region

    Select a region for balancing.

    <Warning>
      **Warning**

      You can balance traffic only within a single data center.
    </Warning>

    ## Step 3. Set computing configuration

    Select a suitable computing configuration for your Load Balancer: vCPU and GiB. All Load Balancers are created in high availability mode with active-standby instances. Upon failure of the active instance, the standby one will seamlessly take over the load-balancing functions.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-2-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=cd4bc6cfe43ed41e4318e4fdee12c014" alt="Select type" width="616" height="431" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-2-lb.png" />
    </Frame>

    Two classes of Load Balancer flavors are available:

    * **Standard** - general-purpose configurations suitable for most workloads, with network throughput up to 1.5 Gbps.
    * **Network-Optimized** - built on network-optimised infrastructure with SR-IOV on the VIP port. These deliver significantly higher packet rates and lower latency, with guaranteed bandwidth up to 10 Gbps per instance.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/lb-type-network-optimized.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=15726a8989e3140eaa26342f92ea86be" alt="Network-Optimized flavor tab" width="616" height="453" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/lb-type-network-optimized.png" />
    </Frame>

    | **vCPU** | **RAM (GiB)** | **Network bandwidth (VIP)** |
    | -------- | ------------- | --------------------------- |
    | 2        | 2             | 1.5 Gbps                    |
    | 4        | 4             | 5 Gbps                      |
    | 8        | 8             | 10 Gbps                     |
    | 16       | 16            | 10 Gbps                     |

    Use Network-Optimized flavors for services that handle large volumes of concurrent connections or high-bandwidth traffic, such as media streaming, CDN origin servers, and API gateways.

    ## Step 4. Configure network

    Configure the network interface:

    1. Select the **Network type**: **Public** or **Private**.

    2. In the **IP Family** section, select the IP version: **IPv4**, **IPv6**, or **Dual (IPv4 + IPv6)**.

    3. (Optional) Enable **Use reserved IP** to assign a [reserved IP address](/cloud/networking/ip-address/create-and-configure-a-reserved-ip-address) to the Load Balancer.

    4. Configure **Preferred connectivity** (L2 or L3) as described in the next step.

           <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/lb-network-section.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=5da6fb885fed4c20343727e1320e348f" alt="Network configuration" width="532" height="238" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/lb-network-section.png" />

    ## Step 5. Configure preferred connectivity

    You can choose between L2 (Layer 2) and L3 (Layer 3) connectivity. This setting determines the preferred connectivity method the Load Balancer uses to connect to backend pool members. If the preferred connectivity is not feasible, traffic will automatically route via the alternative method:

    **L2 (preferred) -> (if not possible) L3 -> (if not possible) Validation Error**

    **L3 (preferred) -> (if not possible) L2 -> (if not possible) Validation Error**

    The Load Balancer determines available routes only by evaluating subnet host routes. Due to current system limitations, it does not take router `host_routes` into account.

    ### Layer 2

    L2 connectivity offers better performance because traffic flows directly between the Load Balancer and pool members without passing through a router. This reduces network hops and minimizes latency.

    However, this approach requires more IP addresses. In networks with many `/24` subnets, each Load Balancer must create ports in every subnet where its members are located. This can lead to high IP utilization and reduced efficiency in large-scale deployments.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-5-preferred-connectivity.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=74162c498dee82b7911474b9eed68bec" alt="Select Layer 2 connectivity option" width="914" height="219" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-5-preferred-connectivity.png" />
    </Frame>

    ### Layer 3

    L3 connectivity routes traffic through a router or gateway, introducing additional network hops that may slightly impact performance.

    It also optimizes IP address utilization by reducing the number of required IPs per Load Balancer. Instead of allocating a separate IP in every subnet, the Load Balancer communicates with pool members across subnets using routing mechanisms. This approach improves scalability and efficiency, especially in environments with multiple subnets.

    <Tip>
      **Tip**

      For most cases, such as a single subnet setup, use **L2 connectivity** for optimal performance. If your deployment involves multiple subnets or complex networking requirements, contact support to determine the best configuration.
    </Tip>

    ## Step 6. Configure listeners

    Add listeners that will check for connection requests using the protocol and port that you specify. You can add multiple listeners to a Load Balancer.

    To configure a listener:

    1. In the **Listeners** section, click **Add listener**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/add-listener.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=c4ed866a657e55bcf9ea0ce3b11f693c" alt="Add listener" width="2848" height="708" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/add-listener.png" />
    </Frame>

    2. Enter the listener's name.

    3. Select the required protocol: TCP, UDP, HTTP, HTTPS, Terminated HTTPS, or Prometheus. You can configure multiple TLS certificates for Terminated HTTPS and Prometheus.

    4. Specify a port that the Load Balancer will listen on for incoming traffic. You can keep a default port for some protocols or specify the needed port from 1 to 65535.

    5. (Optional) To identify the origin of the user's IP address connecting to a web server via a load balancer, enable the **Add headers X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto to requests** toggle.

    6. If you select Terminated HTTPS and Prometheus protocols, you can configure TLS certificates. Follow instructions from our [dedicated guide](/cloud/networking/load-balancers/add-certificates-to-load-balancer).

    7. Set the connection limit: the maximum number of simultaneous connections that can be handled by this listener. The default value is 100,000. Setting the value to -1 sets the limit to the default.

    8. (Optional) Add allowed CIDR ranges to define which IP addresses can access the content. All IP addresses outside the specified ranges will be denied access. Up to 100 CIDR ranges can be specified per listener.

    To ensure correct operation and avoid misconfigurations, the IP version of Allowed CIDRs must match the IP version of the Load Balancer's Virtual IPs (VIPs).

    **Basic Rules:**

    * VIPs with both IPv4 and IPv6 support CIDRs of both versions.

    VIPs: 62.112.222.52 (IPv4), 2a03:90c0:4d6:1::2e8 (IPv6)

    Allowed CIDRs: 10.0.0.0/8, fe00::/7

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-8-edit-listener.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=9239c7190e8784c8684c8abe9a4d79c7" alt="step 8 cidr validation" width="1044" height="704" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-8-edit-listener.png" />
    </Frame>

    * VIPs with only IPv4 allow only IPv4 CIDRs
    * VIPs with only IPv6 allow only IPv6 CIDRs

    If the provided CIDRs do not match the VIP's IP version, the API will return a validation error.

    9. (Optional) For HTTP-based listeners, you can configure basic user authentication to protect your resource from unauthorized access. Click **Add users** to enable the authentication:

    * **Enter username** : specify a username.
    * **Password** : specify a password or choose the **Encrypted password** option to store password as a hash. Check out [create an encrypted password](/cloud/networking/load-balancers/add-certificates-to-load-balancer#create-an-encrypted-password) for instructions.

    <Info>
      **Info**

      A password must contain at least one lowercase character, one uppercase character, at least one number, and a special character. The maximum password length is 128 symbols.
    </Info>

    10. Click **Create Listener**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/configure-listener.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=9faf0173548520723452180a4204eee9" alt="Listener configuration" width="2488" height="2624" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/configure-listener.png" />
    </Frame>

    Listener configuration options differ depending on the selected protocol. For example, HTTP and Terminated HTTPS protocols allow additional settings, such as enabling headers and authentication, while TCP and UDP listeners focus on specifying ports and connection limits.

    ### Pool

    Configure a pool - a list of VMs to which the listener will redirect incoming traffic. Click **Add new pool** in the "Listeners" block to start configuring.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-pools-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=e75214c3399c76fa4e0b06138757e28a" alt="Add pools" width="3580" height="2060" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-pools-lb.png" />
    </Frame>

    1. Specify the pool name.

    2. Select the balancing algorithm:

    * **Round robin** — requests are distributed across servers within a cluster one by one: the first request is sent to the first server, the second request is sent to the second server, and so on in a circle.
    * **Least Connection** — new requests are sent to a server with the fewest active connections.
    * **Source IP** — a client's IP address is used to determine which server receives the request.

    3. Select a pool protocol — the protocol the Load Balancer uses to communicate with backend servers. The available options are: **HTTP**, **HTTPS**, **TCP**, **PROXY**, and **PROXY V2**. The pool protocol is independent from the listener protocol and should match what your backend application expects.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/pool-protocol-dropdown.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=4e42983bef55840cfcef61fe6940f3b9" alt="Pool protocol dropdown showing PROXY and PROXY V2 options" width="822" height="571" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/pool-protocol-dropdown.png" />
    </Frame>

    To preserve the original client IP address on the backend, select **PROXY** (Proxy Protocol v1, text-based) or **PROXY V2** (Proxy Protocol v2, binary). When either option is selected, the Load Balancer prepends a Proxy Protocol header to each TCP connection, allowing backend servers to read the real client IP instead of the Load Balancer's IP.

    <Info>
      **Info**

      PROXY and PROXY V2 require the listener to use the TCP protocol. Your backend application must be configured to parse Proxy Protocol headers. Selecting PROXY or PROXY V2 on a pool whose members do not expect these headers will cause connection failures.
    </Info>

    4. (Optional) Configure **Sticky Sessions** to route repeated requests from the same client to the same backend instance. In the **Sticky Sessions** dropdown, select the session persistence method:

    * **None** — no session persistence, requests are distributed according to the selected algorithm.
    * **App Cookie** — the Load Balancer uses an existing application cookie to route requests. Fill in the **Cookie** field with the cookie name. [A special module](https://code.google.com/p/nginx-sticky-module/) creates a cookie and then uses it to forward requests to the same server.
    * **HTTP Cookie** — the Load Balancer generates and manages its own session cookie automatically.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-pool-conf-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=408ac59eeaf2b74b4a54b0f4980287d3" alt="Pool configuration" width="3372" height="1748" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-pool-conf-lb.png" />
    </Frame>

    **Sharing a pool across multiple listeners**

    A single pool can be used by multiple listeners within the same Load Balancer. This reduces configuration overhead and simplifies pool member management when routing traffic from different ports to the same backend servers.

    <Info>
      **Info**

      Shared pools can only be configured via the [Load Balancer API](https://apidocs.gcore.com/cloud#tag/Load-Balancers).
    </Info>

    To configure a shared pool:

    1. Create a Load Balancer via <code>POST /cloud/v1/loadbalancers/{project_id}/{region_id}</code>.
    2. Create a pool via <code>POST /cloud/v1/lbpools/{project_id}/{region_id}</code>, specifying `loadbalancer_id` without `listener_id`.
    3. Create listeners via <code>POST /cloud/v1/lblisteners/{project_id}/{region_id}</code>, referencing the pool via `default_pool_id`.

    <Warning>
      **Warning**

      When deleting a listener that uses a shared pool, do not use the `delete_default_pool` option. This would delete the pool and affect all other listeners using it. Instead, manage the pool separately.
    </Warning>

    ### Virtual Machine

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-instance-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=8e2243fb4494c08a4d1e44965f0f29fb" alt="Add Virtual Machine" width="2816" height="512" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-instance-lb.png" />
    </Frame>

    Click **Add Instance** to add Virtual Machines that will participate in the traffic distribution for the configured listener.

    1. Select Custom IP, Virtual Machine, or Bare Metal and appropriate configurations.

    2. Specify its port and weight in the distribution.

    ### Health check

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-instance-conf-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=8d9de30b888fbd3bed65a46d5792179d" alt="Configure Health Check" width="3360" height="1404" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-instance-conf-lb.png" />
    </Frame>

    1. Select the protocol for checking: TCP, Ping, HTTP and appropriate configurations.

    2. Specify check interval (sec) - time between sent requests.

    3. Specify response time (sec) - the time to wait for a response from a server.

    4. Specify unhealthy threshold - the number of failed requests after which traffic will no longer be sent to the Virtual Machine.

    5. Specify healthy thresholds - the number of successful requests after which the Virtual Machine will be considered ready to receive traffic.

    ### Timeouts

    Specify client data, member connect and member data timeouts in msec.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-timeouts-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=40a3e67c432ec3cb91fa0f68523e8a44" alt="Configure timeouts" width="3380" height="704" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-4-timeouts-lb.png" />
    </Frame>

    Each terminated HTTPS listener requires a default TLS certificate. Additional SNI certificates can also be configured, allowing multiple certificates to be assigned to the same listener.

    ## Step 7. Enter the name

    Enter a name for the Load Balancer. This name will be displayed in the Gcore Customer Portal.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-6-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=7fe36bb2dded39e24a6c2195453e349f" alt="Enter Load Balancer name" width="3568" height="768" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-6-lb.png" />
    </Frame>

    ## Step 8. (Optional) Enable logging

    The Logging service will be activated to store your logs. To learn how it works and how to configure it, refer to the article about [Logging](/cloud/logging-as-a-service/about-logging-as-a-service).

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-7-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=5e0e48c410e0fb8301399cba94a5673c" alt="Configure Logging" width="3352" height="2608" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-7-lb.png" />
    </Frame>

    ## Step 9. (Optional) Add tags

    Create tags for your load balancer by entering "Key" and "Value".

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/O2fvsv9KLjD8CjMq/images/docs/cloud/networking/create-and-configure-a-load-balancer/step-8-lb.png?fit=max&auto=format&n=O2fvsv9KLjD8CjMq&q=85&s=3ac556c77eecfdc20eac7aa463db272c" alt="Configure tags" width="3568" height="1000" data-path="images/docs/cloud/networking/create-and-configure-a-load-balancer/step-8-lb.png" />
    </Frame>

    ## Step 10. Finalize creation

    Check the settings and click **Create Load Balancer** on the right.

    ## Step 11. Configure firewall

    Configure firewalls for Virtual Machines in the pool according to the [separate guide](/cloud/networking/add-and-configure-a-firewall).

    Make sure their ports are open for the Load Balancer traffic:

    * If a Load Balancer and Virtual Machines are in a **public network,** set a rule to receive and transmit traffic to the balancer's IP address (specified in the menu) in firewalls settings of the VM.
    * If a Load Balancer and Virtual Machines are in a **private subnetwork,** set a rule to receive and transmit traffic to the entire private subnetwork or to the balancer's IP address (specified in the menu).
    * If a Load Balancer is in a **public network** and Virtual Machine are in a **private subnetwork**, set a rule to receive and transmit traffic to the entire private subnetwork or to the balancer's internal IP address (send a request to the technical support).
  </MethodSection>

  <MethodSection id="api" label="REST API">
    A [load balancer](https://gcore.com/docs/api-reference/cloud/load-balancers/create-load-balancer) distributes incoming requests across backend VMs, routing traffic only to healthy members. Creating one requires four API calls: create the balancer, add a listener, create a pool, and register the backend VMs as pool members.

    <Info>
      A permanent [API token](/account-settings/api-tokens) is required, along with a [project ID](https://gcore.com/docs/api-reference/cloud/projects/list-projects) and [region ID](https://gcore.com/docs/api-reference/cloud/regions/list-regions).
    </Info>

    Open a bash terminal and set these as environment variables before running the examples:

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    export VM1_IP="{VM1_PUBLIC_IP}"
    export VM2_IP="{VM2_PUBLIC_IP}"
    ```

    <Info>
      **VM1\_IP** and **VM2\_IP** are the public IP addresses of the virtual machines that will serve as backend pool members. To create VMs and find their IPs, see [Create a virtual machine](/cloud/virtual-instances/create-an-instance).
    </Info>

    ## Quickstart

    The scripts below create a load balancer with an HTTP listener and a round-robin pool, then add two backend VMs as pool members. Set `VM1_IP` and `VM2_IP` to the public IP addresses of running VMs.

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import os
        from gcore import Gcore

        client = Gcore()

        # Step 1. List flavors and pick the smallest
        flavors = client.cloud.load_balancers.flavors.list()
        lb_flavor = flavors.results[0].flavor_name
        print(f"Flavor: {lb_flavor}")

        # Step 2. Create load balancer (takes about 1 minute)
        lb = client.cloud.load_balancers.create_and_poll(
            name="my-lb",
            flavor=lb_flavor,
            polling_timeout_seconds=300,
        )
        print(f"LB VIP: {lb.vip_address}")

        # Step 3. Create HTTP listener on port 80
        listener = client.cloud.load_balancers.listeners.create_and_poll(
            load_balancer_id=lb.id,
            name="http-listener",
            protocol="HTTP",
            protocol_port=80,
        )

        # Step 4. Create round-robin pool
        pool = client.cloud.load_balancers.pools.create_and_poll(
            name="http-pool",
            lb_algorithm="ROUND_ROBIN",
            protocol="HTTP",
            listener_id=listener.id,
            load_balancer_id=lb.id,
        )

        # Step 5. Add backend VMs as pool members
        for ip in [os.environ["VM1_IP"], os.environ["VM2_IP"]]:
            t = client.cloud.load_balancers.pools.members.create(
                pool_id=pool.id,
                address=ip,
                protocol_port=80,
            )
            client.cloud.tasks.poll(t.tasks[0], polling_interval_seconds=5, polling_timeout_seconds=120)

        print(f"Traffic on {lb.vip_address}:80 is now distributed across both VMs")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.TODO()

            // Step 1. List flavors and pick the smallest
            flavors, err := client.Cloud.LoadBalancers.Flavors.List(ctx, cloud.LoadBalancerFlavorListParams{})
            if err != nil {
                panic(err.Error())
            }
            lbFlavor := flavors.Results[0].FlavorName
            fmt.Printf("Flavor: %s\n", lbFlavor)

            // Step 2. Create load balancer (takes about 1 minute)
            lb, err := client.Cloud.LoadBalancers.NewAndPoll(ctx, cloud.LoadBalancerNewParams{
                Name:   "my-lb",
                Flavor:    gcore.String(lbFlavor),
            })
            if err != nil {
                panic(err.Error())
            }
            fmt.Printf("LB VIP: %s\n", lb.VipAddress)

            // Step 3. Create HTTP listener on port 80
            listener, err := client.Cloud.LoadBalancers.Listeners.NewAndPoll(ctx, cloud.LoadBalancerListenerNewParams{
                LoadBalancerID: lb.ID,
                Name:           "http-listener",
                Protocol:       "HTTP",
                ProtocolPort:   80,
            })
            if err != nil {
                panic(err.Error())
            }

            // Step 4. Create round-robin pool
            pool, err := client.Cloud.LoadBalancers.Pools.NewAndPoll(ctx, cloud.LoadBalancerPoolNewParams{
                Name:           "http-pool",
                LbAlgorithm:    "ROUND_ROBIN",
                Protocol:       "HTTP",
                ListenerID:     gcore.String(listener.ID),
                LoadBalancerID: gcore.String(lb.ID),
            })
            if err != nil {
                panic(err.Error())
            }

            // Step 5. Add backend VMs as pool members
            for _, ip := range []string{os.Getenv("VM1_IP"), os.Getenv("VM2_IP")} {
                t, err := client.Cloud.LoadBalancers.Pools.Members.New(ctx, pool.ID, cloud.LoadBalancerPoolMemberNewParams{
                    Address:      ip,
                    ProtocolPort: 80,
                })
                if err != nil {
                    panic(err.Error())
                }
                if _, err = client.Cloud.Tasks.Poll(ctx, t.Tasks[0]); err != nil {
                    panic(err.Error())
                }
            }
            fmt.Printf("Traffic on %s:80 is now distributed across both VMs\n", lb.VipAddress)
        }
        ```
      </Tab>
    </Tabs>

    ## Step-by-step

    <p>Each step below explains what the call does, which parameters matter, and what the response looks like. Use this section to understand the flow or to debug a specific step.</p>

    <Accordion title="Show all steps">
      ### Step 1. List load balancer flavors

      A [flavor](https://gcore.com/docs/api-reference/cloud/load-balancers/list-load-balancer-flavors) determines the vCPU count, RAM, and maximum network throughput of the load balancer instance. Flavor availability is region-specific — run this call to see what's available in the target region.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          import os
          from gcore import Gcore

          client = Gcore()

          flavors = client.cloud.load_balancers.flavors.list()
          for f in flavors.results:
              print(f.flavor_name, f.vcpus, "vCPU /", f.ram // 1024, "GB")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          flavors, err := client.Cloud.LoadBalancers.Flavors.List(ctx, cloud.LoadBalancerFlavorListParams{})
          if err != nil {
              panic(err.Error())
          }
          for _, f := range flavors.Results {
              fmt.Printf("%s: %d vCPU / %d MB RAM\n", f.FlavorName, f.Vcpus, f.Ram)
          }
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl "https://api.gcore.com/cloud/v1/lbflavors/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY"
          ```

          Response:

          ```json theme={null}
          {
            "count": 4,
            "results": [
              {"flavor_id": "fca2fc7c-...", "flavor_name": "lb1-1-2", "vcpus": 1, "ram": 2048},
              {"flavor_id": "b5e956d8-...", "flavor_name": "lb1-2-4", "vcpus": 2, "ram": 4096},
              {"flavor_id": "...",          "flavor_name": "lb1-4-8", "vcpus": 4, "ram": 8192},
              {"flavor_id": "...",          "flavor_name": "lb1-8-16","vcpus": 8, "ram": 16384}
            ]
          }
          ```
        </Tab>
      </Tabs>

      The `flavor_name` value (`lb1-1-2`) is used in the next step. The `flavor_id` UUID is not accepted by the create endpoint.

      ```bash theme={null}
      export LB_FLAVOR="lb1-1-2"
      ```

      ### Step 2. Create the load balancer

      Creating the load balancer without specifying a network assigns a public VIP automatically. Provisioning takes about 1 minute.

      | Parameter | Required | Description                                                     |
      | --------- | -------- | --------------------------------------------------------------- |
      | `name`    | Yes      | Display name for the load balancer.                             |
      | `flavor`  | Yes      | The `flavor_name` string from step 1, not the `flavor_id` UUID. |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          lb = client.cloud.load_balancers.create_and_poll(
              name="my-lb",
              flavor=os.environ["LB_FLAVOR"],
              polling_timeout_seconds=300,
          )
          print(f"LB ID: {lb.id}  VIP: {lb.vip_address}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          lb, err := client.Cloud.LoadBalancers.NewAndPoll(ctx, cloud.LoadBalancerNewParams{
              Name:   "my-lb",
              Flavor:    gcore.String(os.Getenv("LB_FLAVOR")),
          })
          if err != nil {
              panic(err.Error())
          }
          fmt.Printf("LB ID: %s  VIP: %s\n", lb.ID, lb.VipAddress)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v1/loadbalancers/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"name": "my-lb", "flavor": "'"$LB_FLAVOR"'"}'
          ```

          Response:

          ```json theme={null}
          {"tasks": ["d4a4b10e-..."]}
          ```

          Poll <code>GET /cloud/v1/tasks/{task_id}</code> every 5 seconds until `state` is `FINISHED`. Then retrieve the VIP address:

          ```bash theme={null}
          curl "https://api.gcore.com/cloud/v1/loadbalancers/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$LB_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY"
          ```

          ```json theme={null}
          {
            "id": "f0782954-...",
            "provisioning_status": "ACTIVE",
            "operating_status": "ONLINE",
            "vip_address": "85.234.84.36"
          }
          ```
        </Tab>
      </Tabs>

      Save the load balancer ID and VIP for later steps:

      ```bash theme={null}
      export LB_ID="{LB_ID}"
      export LB_VIP="{LB_VIP_ADDRESS}"
      ```

      ### Step 3. Create a listener

      A [listener](https://gcore.com/docs/api-reference/cloud/load-balancers/create-load-balancer-listener) watches for incoming connections on a specific protocol and port, then forwards them to a pool.

      | Parameter          | Required | Description                                  |
      | ------------------ | -------- | -------------------------------------------- |
      | `load_balancer_id` | Yes      | The LB ID from step 2.                       |
      | `protocol`         | Yes      | `HTTP`, `TCP`, `UDP`, or `TERMINATED_HTTPS`. |
      | `protocol_port`    | Yes      | Port to listen on (1–65535).                 |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          listener = client.cloud.load_balancers.listeners.create_and_poll(
              load_balancer_id=lb.id,
              name="http-listener",
              protocol="HTTP",
              protocol_port=80,
          )
          print(f"Listener ID: {listener.id}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          listener, err := client.Cloud.LoadBalancers.Listeners.NewAndPoll(ctx, cloud.LoadBalancerListenerNewParams{
              LoadBalancerID: lb.ID,
              Name:           "http-listener",
              Protocol:       "HTTP",
              ProtocolPort:   80,
          })
          if err != nil {
              panic(err.Error())
          }
          fmt.Printf("Listener ID: %s\n", listener.ID)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v1/lblisteners/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "http-listener",
              "load_balancer_id": "'"$LB_ID"'",
              "protocol": "HTTP",
              "protocol_port": 80
            }'
          ```

          Response:

          ```json theme={null}
          {"tasks": ["f1e2d3c4-..."]}
          ```

          Poll until `FINISHED`, then save the listener ID from `created_resources.listeners[0]`.
        </Tab>
      </Tabs>

      ```bash theme={null}
      export LISTENER_ID="{LISTENER_ID}"
      ```

      ### Step 4. Create a pool

      A [pool](https://gcore.com/docs/api-reference/cloud/load-balancers/create-load-balancer-pool) groups the backend VMs and distributes requests across them according to the chosen algorithm.

      | Parameter          | Required | Description                                                |
      | ------------------ | -------- | ---------------------------------------------------------- |
      | `listener_id`      | Yes      | Attaches this pool to the listener from step 3.            |
      | `load_balancer_id` | Yes      | The LB ID from step 2.                                     |
      | `lb_algorithm`     | Yes      | `ROUND_ROBIN`, `LEAST_CONNECTIONS`, or `SOURCE_IP`.        |
      | `protocol`         | Yes      | Must match the listener protocol (`HTTP` in this example). |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          pool = client.cloud.load_balancers.pools.create_and_poll(
              name="http-pool",
              lb_algorithm="ROUND_ROBIN",
              protocol="HTTP",
              listener_id=listener.id,
              load_balancer_id=lb.id,
          )
          print(f"Pool ID: {pool.id}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          pool, err := client.Cloud.LoadBalancers.Pools.NewAndPoll(ctx, cloud.LoadBalancerPoolNewParams{
              Name:           "http-pool",
              LbAlgorithm:    "ROUND_ROBIN",
              Protocol:       "HTTP",
              ListenerID:     gcore.String(listener.ID),
              LoadBalancerID: gcore.String(lb.ID),
          })
          if err != nil {
              panic(err.Error())
          }
          fmt.Printf("Pool ID: %s\n", pool.ID)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v1/lbpools/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "http-pool",
              "lb_algorithm": "ROUND_ROBIN",
              "protocol": "HTTP",
              "listener_id": "'"$LISTENER_ID"'",
              "load_balancer_id": "'"$LB_ID"'"
            }'
          ```

          Response:

          ```json theme={null}
          {"tasks": ["a2b3c4d5-..."]}
          ```

          Poll until `FINISHED`, then save the pool ID from `created_resources.lbpools[0]`.
        </Tab>
      </Tabs>

      ```bash theme={null}
      export POOL_ID="{POOL_ID}"
      ```

      ### Step 5. Add backend VMs as pool members

      Each [pool member](https://gcore.com/docs/api-reference/cloud/load-balancers/create-load-balancer-pool-member) is a VM identified by its IP address and the port where the application listens. Repeat this call for each VM.

      | Parameter       | Required | Description                                             |
      | --------------- | -------- | ------------------------------------------------------- |
      | `address`       | Yes      | The VM's public IP address.                             |
      | `protocol_port` | Yes      | The port the application is listening on inside the VM. |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          for ip in [os.environ["VM1_IP"], os.environ["VM2_IP"]]:
              t = client.cloud.load_balancers.pools.members.create(
                  pool_id=pool.id,
                  address=ip,
                  protocol_port=80,
              )
              client.cloud.tasks.poll(t.tasks[0], polling_interval_seconds=5, polling_timeout_seconds=120)
              print(f"Added {ip} to pool")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          for _, ip := range []string{os.Getenv("VM1_IP"), os.Getenv("VM2_IP")} {
              t, err := client.Cloud.LoadBalancers.Pools.Members.New(ctx, pool.ID, cloud.LoadBalancerPoolMemberNewParams{
                  Address:      ip,
                  ProtocolPort: 80,
              })
              if err != nil {
                  panic(err.Error())
              }
              if _, err = client.Cloud.Tasks.Poll(ctx, t.Tasks[0]); err != nil {
                  panic(err.Error())
              }
              fmt.Printf("Added %s to pool\n", ip)
          }
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          # Add VM1 (repeat for VM2 with its IP)
          curl -X POST "https://api.gcore.com/cloud/v1/lbpools/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$POOL_ID/member" \
            -H "Authorization: APIKey $GCORE_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"address": "'"$VM1_IP"'", "protocol_port": 80}'
          ```

          Response:

          ```json theme={null}
          {"tasks": ["c3d4e5f6-..."]}
          ```

          Poll until `FINISHED`, then repeat for VM2.
        </Tab>
      </Tabs>

      Members show `operating_status: NO_MONITOR` when no health monitor is configured — this is expected. The load balancer still distributes traffic. To enable automatic member removal when a backend becomes unhealthy, add a [health monitor](https://gcore.com/docs/api-reference/cloud/load-balancers/create-load-balancer-pool-health-monitor) to the pool.

      ### Step 6. Verify the load balancer

      After adding both members, confirm the load balancer is active and traffic is flowing. The [load balancers](https://gcore.com/docs/api-reference/cloud/load-balancers) endpoint also supports updating listeners, resizing the flavor, enabling logging, and configuring DDoS protection.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          fetched = client.cloud.load_balancers.get(load_balancer_id=lb.id)
          print(f"Status: {fetched.provisioning_status} / {fetched.operating_status}")
          print(f"VIP: {fetched.vip_address}")
          print(f"Listeners: {len(fetched.listeners)}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          fetched, err := client.Cloud.LoadBalancers.Get(ctx, lb.ID, cloud.LoadBalancerGetParams{})
          if err != nil {
              panic(err.Error())
          }
          fmt.Printf("Status: %s / %s\n", fetched.ProvisioningStatus, fetched.OperatingStatus)
          fmt.Printf("VIP: %s  Listeners: %d\n", fetched.VipAddress, len(fetched.Listeners))
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl "https://api.gcore.com/cloud/v1/loadbalancers/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$LB_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY"
          ```

          Response:

          ```json theme={null}
          {
            "id": "f0782954-...",
            "provisioning_status": "ACTIVE",
            "operating_status": "ONLINE",
            "vip_address": "85.234.84.36",
            "listeners": [{"id": "d2ac5700-..."}]
          }
          ```
        </Tab>
      </Tabs>

      Incoming HTTP traffic on port 80 is now distributed across both VMs using round-robin.
    </Accordion>

    ## Clean up

    Deleting the load balancer removes the listener, pool, and members automatically. Delete the load balancer:

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        client.cloud.load_balancers.delete_and_poll(
            load_balancer_id=lb.id,
            polling_timeout_seconds=300,
        )
        print("Load balancer deleted.")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        err = client.Cloud.LoadBalancers.DeleteAndPoll(ctx, lb.ID, cloud.LoadBalancerDeleteParams{})
        if err != nil {
            panic(err.Error())
        }
        fmt.Println("Load balancer deleted.")
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X DELETE \
          "https://api.gcore.com/cloud/v1/loadbalancers/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$LB_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY"
        ```

        Response:

        ```json theme={null}
        {"tasks": ["e5f6g7h8-..."]}
        ```

        Poll until `FINISHED`.
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
