> For the complete documentation index, see [llms.txt](https://docs.tumbler.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tumbler.app/features/balancing.md).

# Balancing

## Who this is for

Providers who want to distribute traffic across multiple nodes or regions and control which node the client chooses first.

## What is a node group

* A logical label for nodes that share one capacity pool or region, for example one cluster/datacenter.
* Used by the client for grouping and by ACC for counters with `group` scope.
* Nodes without `group` are treated as independent.

### How to set group

* **VLESS link:** query `group=<string>` -> stored in `node.meta.group`.
* **JSON node:** `meta: { "group": "eu-west" }`.
* Make the string stable and meaningful (region, datacenter, plan). Same string means same group.

## Balancing methods (`balancer-method`)

Field in `meta` or header (`balancer-method: ping|connections`). When empty, node order is not changed.

### When to choose `ping`

* Nodes are in different regions/channels, and the main goal is minimum RTT for the user.
* You are ready to send client ping metrics (`ping_result` events).

**How it works:**

* The client measures RTT to a specific node and sends `ping_result` with `rtt_ms`; backend stores EMA (alpha 0.3) with TTL around 24h.
* Reordering happens only when improvement is >20% and at least 30 ms, with a cooldown of around 10 minutes between switches.
* If there are no metrics, order stays as returned by the provider.

### When to choose `connections`

* Nodes are in one region or have similar latency, and even load distribution matters more.
* Client telemetry is not required: the backend counts active sessions per node itself.

**What counts as an active connection:**

* A session is created through the API, receives a lease for around 90 seconds; heartbeat extends it, explicit `end` or expiry decreases the counter.
* Per-node counters are stored in Redis for around 24h. Leader switch requires >20% improvement (minimum 1 connection) and also respects the around-10-minute cooldown.

## Compatibility with **\[PAID]** ACC

* ACC with `group` scope uses the same `meta.group` values; set them consistently on all nodes in the group.
* The balancer only changes node order; ACC counters continue to work by the selected scope (`subscription`/`config`/`group`).
* With per-group limits, do not mix different physical locations under one `group`, so limits reflect real capacity.

## Anti-patterns and flapping

* Frequently changing `group`/query parameters/node name changes `node_id`, loses accumulated metrics, and makes order jump.
* Enabling `ping` but not sending `ping_result`, or sending it only for rare nodes, means the order will not update and the client stays on the original node.
* Mixing distant regions without groups: with `ping`, the client may jump between continents; mark regions with `group` and keep predictable priority (primary -> reserve).
* Constantly reshuffling the list manually while the balancer is enabled: cooldown (10 min) and significance thresholds prevent some flapping, but stable `node_id` and static base order are more reliable.

## Short recommendations

* Explicitly set `balancer-method` and use one signal: RTT (`ping`) or actual load (`connections`).
* Mark nodes with `group` if you split capacity by clusters/regions or plan per-group ACC limits.
* For reserves, keep the same `group` but put them lower in the list/with lower weight; update `version_id` when membership changes.
* Include regions/zones in names if they matter for user choice.

## See also

* [features/overview.md](/features/overview.md)
* [features/advanced-connection-control.md](/features/advanced-connection-control.md)
* [operations/reliability-and-timeouts.md](/after-first-launch/reliability-and-timeouts.md)
* [subscription/examples.md](/subscription-contract/examples.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tumbler.app/features/balancing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
