# Xray-core Routing Strategies for Load Balancing: Random, LeastPing, LeastLoad, and RoundRobin Explained

> Explore Xray-core routing strategies for load balancing: random, leastping, leastload, and roundrobin. Optimize traffic distribution across outbounds for better performance.

- Repository: [Project X Community, Not Porn-jet X Hub/Xray-core](https://github.com/XTLS/Xray-core)
- Tags: deep-dive
- Published: 2026-04-21

---

**Xray-core supports four distinct load-balancing routing strategies—`random`, `leastping`, `leastload`, and `roundrobin`—that distribute traffic across candidate outbounds using uniform selection, latency-based metrics, computed load costs, or sequential rotation.**

The XTLS/Xray-core repository implements a sophisticated routing system that balances outbound traffic across multiple proxy candidates. These routing strategies integrate with the observatory feature to make intelligent selection decisions based on real-time health data, enabling high-availability deployments that automatically avoid failed or high-latency nodes.

## How Xray-core Routing Strategies Work

The router implements a pipeline that bridges configuration and runtime selection. According to the source code in [`app/router/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/config.go), the `Build` method matches the textual `Strategy` value from your configuration and creates a `Balancer` object that embeds the concrete strategy implementation.

When a routing rule requires an outbound tag, the `Balancer.PickOutbound` method delegates to the specific strategy's selection logic. Most strategies (except `roundrobin`) request the latest health observations from the `extension.Observatory` feature, which reports per-outbound latency, alive status, and health statistics.

## Supported Load-Balancing Strategies

### Random Strategy

The **RandomStrategy** provides uniform random selection across all candidate outbounds. Implemented in [`app/router/strategy_random.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_random.go), this strategy uses the `dice.Roll` helper function to pick candidates uniformly at random. When the observatory is enabled, it filters out dead outbounds before selection. If no candidates are alive and a `fallbackTag` is defined, the balancer routes traffic to the fallback.

**Configuration key:** `"type": "random"`

### Least Ping Strategy

The **LeastPingStrategy** selects the outbound with the smallest observed latency. Defined in [`app/router/strategy_leastping.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_leastping.go), this strategy scans the observation list maintained by the observatory and keeps the node with the minimum `Delay` value (using `int64(99999999)` as a sentinel for uninitialized values). Only outbounds marked as alive in the observatory are considered for selection.

**Configuration key:** `"type": "leastping"`

### Round Robin Strategy

The **RoundRobinStrategy** cycles through candidates sequentially without consulting health data. Defined in [`app/router/balancing.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/balancing.go), this strategy maintains an atomic index (`next`) that advances modulo the candidate count. Because it does not check the observatory, dead outbounds can be selected unless you configure a fallback tag to handle total failure scenarios.

**Configuration key:** `"type": "roundrobin"`

### Least Load Strategy

The **LeastLoadStrategy** offers the most sophisticated selection logic, computing a *load cost* for each outbound based on RTT, failure counts, and configurable weights. Implemented in [`app/router/strategy_leastload.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_leastload.go), this strategy:

- Builds a `WeightManager` from `StrategyWeight` entries using the cost formula `value * cost^0.5`
- Retrieves health data via `observer.GetObservation`
- Constructs `node` objects containing RTT, deviation, failure count, and computed `RTTDeviationCost`
- Applies *Baselines* and *Expected* settings in `selectLeastLoad` to prune candidates and return the optimal node(s)

Configuration structures for this strategy reside in [`infra/conf/router_strategy.go`](https://github.com/XTLS/Xray-core/blob/main/infra/conf/router_strategy.go) within the `StrategyLeastLoadConfig` struct.

**Configuration key:** `"type": "leastload"`

## Configuration Examples

### LeastLoad with Weights and Baselines

```yaml
routing:
  rules:
    - inboundTag: ["in"]
      balancer:
        outboundSelector: ["out1", "out2", "out3"]
        strategy: "leastload"
        fallbackTag: "fallback"
        settings:
          costs:
            - tag: "out1"
              weight: 1
            - tag: "out2"
              weight: 2
          baselines: [50ms, 100ms]
          expected: 2
          maxRTT: 200ms
          tolerance: 0.2

```

### Random Strategy with Fallback

```json
{
  "routing": {
    "rules": [
      {
        "inboundTag": ["in"],
        "balancer": {
          "outboundSelector": ["outA", "outB", "outC"],
          "strategy": "random",
          "fallbackTag": "fallback"
        }
      }
    ]
  }
}

```

### RoundRobin Configuration

```toml
[routing.rules]
inboundTag = ["in"]

[routing.rules.balancer]
outboundSelector = ["out1","out2"]
strategy = "roundrobin"

```

### LeastPing Setup

```yaml
routing:
  rules:
    - inboundTag: ["in"]
      balancer:
        outboundSelector: ["outX","outY"]
        strategy: "leastping"

```

## Strategy Configuration Pipeline

The system binds configuration to implementation through three specific mechanisms:

1. **Configuration parsing** — The `strategyConfigLoader` in [`infra/conf/router_strategy.go`](https://github.com/XTLS/Xray-core/blob/main/infra/conf/router_strategy.go) reads the strategy field and loads the appropriate configuration object.

2. **Balancer construction** — Inside [`app/router/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/config.go), the `Build` method instantiates a `Balancer` that embeds the concrete strategy (random, leastping, roundrobin, or leastload).

3. **Runtime selection** — The `Balancer.PickOutbound` method calls `strategy.PickOutbound(candidates)`, passing the filtered list of available outbounds.

## Key Implementation Files

- [`app/router/strategy_random.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_random.go) — Implements **RandomStrategy** with `dice.Roll` selection
- [`app/router/strategy_leastping.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_leastping.go) — Implements **LeastPingStrategy** with RTT comparison
- [`app/router/balancing.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/balancing.go) — Defines **RoundRobinStrategy** and generic `Balancer` logic
- [`app/router/strategy_leastload.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_leastload.go) — Implements **LeastLoadStrategy** with weight management and cost calculation
- [`infra/conf/router_strategy.go`](https://github.com/XTLS/Xray-core/blob/main/infra/conf/router_strategy.go) — Maps strategy names to config structs like `StrategyLeastLoadConfig`
- [`app/router/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/config.go) — Contains the `Build` method that wires strategies to balancers

## Summary

- **Four strategies** are available: `random`, `leastping`, `roundrobin`, and `leastload`
- **Observatory integration** provides health data to `random`, `leastping`, and `leastload`, while `roundrobin` operates blindly
- **LeastLoad** offers the most customization, supporting weighted costs, RTT baselines, and expected node counts for fine-grained control
- **Fallback tags** ensure traffic routing continues when all candidates fail health checks
- Configuration occurs within router rules using the `strategy` field, with strategy-specific settings defined in the `settings` object

## Frequently Asked Questions

### Which routing strategy performs best for high-latency networks?

**Use `leastping` or `leastload`** for high-latency networks. The `leastping` strategy explicitly selects the outbound with the smallest observed RTT from the observatory, while `leastload` incorporates RTT deviation and failure counts into its cost calculation. Both avoid routing traffic through high-latency nodes, unlike `random` or `roundrobin`.

### Does the roundrobin strategy check if outbounds are alive?

**No.** According to the implementation in [`app/router/balancing.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/balancing.go), `RoundRobinStrategy` maintains an atomic counter (`next`) and cycles through candidates modulo the list length without consulting the observatory. Dead outbounds receive traffic unless you configure a `fallbackTag` to handle total balancer failure.

### How does the leastload strategy calculate cost for each outbound?

**The strategy uses a `WeightManager` that applies the formula `value * cost^0.5`** as defined in [`app/router/strategy_leastload.go`](https://github.com/XTLS/Xray-core/blob/main/app/router/strategy_leastload.go). It retrieves health observations including RTT and failure counts, then computes `RTTDeviationCost` for each node. The final selection considers optional baselines and the expected number of nodes to return, allowing bandwidth and speed prioritization.

### Can I use different routing strategies for different inbound tags?

**Yes.** Each routing rule in the configuration defines its own balancer with an independent `strategy` field. You can configure `leastping` for latency-sensitive applications while using `random` for general traffic, assigning each configuration to specific `inboundTag` values within the same Xray-core instance.