# Shadowsocks Windows Server Auto-Switching Strategies: Load Balance and High Availability Implementation

> Explore Shadowsocks Windows server auto-switching strategies like load balance and high availability. Learn how WeightedRoundRobin, AutoSwitch, and failover logic improve your proxy performance.

- Repository: [shadowsocks/shadowsocks-windows](https://github.com/shadowsocks/shadowsocks-windows)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Shadowsocks-Windows v4 implements five distinct server auto-switching strategies—including WeightedRoundRobin, InheritWeight, Legacy, AutoSwitch, and Normal—that control how the client selects proxy servers from a configuration list, with specific logic handling load distribution, backward compatibility, and automatic failover based on health checks.**

The shadowsocks/shadowsocks-windows repository provides robust server selection mechanisms for users managing multiple proxy endpoints. Understanding these **server auto-switching strategies** enables administrators to optimize connection reliability through load balancing or ensure high availability through automatic failover when specific servers become unreachable.

## The Five Server Auto-Switching Strategies

The client supports five selection modes defined in the `enumAutoSwitchStrategy` enumeration within [`shadowsocks-csharp/Model/Server.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/shadowsocks-csharp/Model/Server.cs) (lines 28-49). Each strategy determines how the `ServerSelector` class picks an endpoint from the configured server list.

### WeightedRoundRobin (Load Balancing)

**WeightedRoundRobin** (`0`) distributes incoming connections across servers proportionally based on assigned weights (default 100). The algorithm maintains a circular index and a "remaining-weight" counter; each request decrements this counter by the server's weight value. When the counter reaches zero or below, the selector advances to the next server and resets the counter, ensuring weighted distribution across the server pool.

### InheritWeight (Per-Server Load Balancing)

**InheritWeight** (`1`) operates similarly to WeightedRoundRobin but reads weight values from individual `Server` object properties rather than using uniform defaults. This strategy mirrors the original Android client behavior, allowing granular control where specific servers receive higher or lower traffic allocation based on their configured `Weight` property in [`Server.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/Server.cs).

### Legacy (Backward Compatibility)

**Legacy** (`2`) provides compatibility with older Shadowsocks-Windows releases. When selected, the selector consistently returns `Configuration.ServerList[0]`—the first server in the configuration list—unless the user manually switches servers through the UI. This mode disables dynamic balancing entirely, preserving pre-v4 behavior for existing deployments.

### AutoSwitch (High Availability)

**AutoSwitch** (`5`) implements high-availability through continuous health monitoring. A background `ServerHealthChecker` task (instantiated when this strategy is active) periodically pings each server to record latency in `Server.Latency` and track failure counts. When the active server's failure counter exceeds the configurable threshold, the selector automatically invokes `SwitchToBestServer()`, which chooses the healthiest alternative based on recent latency metrics or weight values.

### Normal (Manual Selection)

**Normal** (`10`) represents the default manual mode. The selector respects the user's explicit "Current Server" choice without applying automatic switching, load balancing, or health-check logic. The UI simply returns the manually selected server instance unchanged.

## Implementation Architecture

The server auto-switching system spans multiple components across the Model, Controller, and View layers.

### Enum Definition in Server.cs

The strategy types are defined in [`shadowsocks-csharp/Model/Server.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/shadowsocks-csharp/Model/Server.cs) at lines 28-49 as `public enum enumAutoSwitchStrategy`. Each member includes XML documentation comments explaining its purpose, with integer values (0, 1, 2, 5, 10) ensuring backward compatibility when configurations are serialized to JSON.

### Configuration Persistence

The selected strategy persists in [`config.json`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/config.json) as the `AutoSwitchStrategy` field within each server entry. During application startup, `Configuration.Load()` deserializes these values and populates the `Server.AutoSwitchStrategy` property for each configured endpoint.

### Server Selection Logic

The `ServerSelector` class (located in [`shadowsocks-csharp/Controller/ServerSelector.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/shadowsocks-csharp/Controller/ServerSelector.cs)) implements the dispatch logic. It examines the `AutoSwitchStrategy` value of the current configuration and routes selection to the appropriate handler:

- `SelectWeightedRoundRobin()` implements the circular weight-based algorithm
- `SelectInheritWeight()` applies per-server weight properties
- `SelectLegacy()` returns the first list element
- `SelectAutoSwitch()` coordinates with the health checker and triggers failovers
- `SelectNormal()` returns the user-selected server directly

### Health Monitoring for AutoSwitch

When `AutoSwitch` mode is active, the `ServerHealthChecker` class ([`shadowsocks-csharp/Controller/ServerHealthChecker.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/shadowsocks-csharp/Controller/ServerHealthChecker.cs)) executes periodic TCP connectivity checks. It maintains failure counters for each `Server` instance and updates latency measurements. Upon detecting that the active server's failures exceed `MaxFailures`, it signals `ServerSelector.SwitchToBestServer()` to evaluate alternatives using the healthiest-available criteria.

### UI Configuration Layer

Users interact with these strategies through the **Server Sharing** dialog. The `ServerSharingView.xaml` defines a combo box bound to `Server.AutoSwitchStrategy`, while [`ServerSharingViewModel.cs`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/ServerSharingViewModel.cs) handles the change notification. When a user selects a different strategy, the view model calls `Configuration.Save()`, ensuring subsequent connections utilize the new selection logic immediately.

## Practical Code Implementation

### Enabling AutoSwitch Mode Programmatically

Configure all servers to use high-availability failover:

```csharp
// Assume `config` is the loaded Configuration instance
foreach (var srv in config.ServerList)
{
    srv.AutoSwitchStrategy = enumAutoSwitchStrategy.AutoSwitch;
}
config.Save();               // persists the change to config.json
ServerSelector.Start();      // reinitializes the selector with new strategy

```

### Implementing Weighted Round Robin Selection

Programmatically request the next server using weight-based distribution:

```csharp
var selector = new ServerSelector();
selector.SetStrategy(enumAutoSwitchStrategy.WeightedRoundRobin);
var server = selector.GetNextServer();   // returns server based on weight algorithm

```

### Handling Health-Check Failures

The health checker automatically triggers failover when thresholds are exceeded:

```csharp
// Inside ServerHealthChecker.cs monitoring loop
if (activeServer.FailureCount > MaxFailures)
{
    selector.SwitchToBestServer();   // selects healthiest alternative automatically
}

```

## Summary

- **Five distinct strategies** exist in `enumAutoSwitchStrategy` (Server.cs lines 28-49): WeightedRoundRobin, InheritWeight, Legacy, AutoSwitch, and Normal
- **WeightedRoundRobin** and **InheritWeight** provide load balancing through weight-based distribution algorithms in `ServerSelector`
- **AutoSwitch** implements high availability via `ServerHealthChecker` monitoring latency and failure counts to trigger automatic failover
- **Legacy** mode maintains backward compatibility by always selecting the first configured server
- **Normal** mode disables automation, respecting only manual user selection
- Configuration persists in [`config.json`](https://github.com/shadowsocks/shadowsocks-windows/blob/main/config.json) and binds to the UI through `ServerSharingViewModel` and `ServerSharingView.xaml`

## Frequently Asked Questions

### What is the difference between WeightedRoundRobin and InheritWeight strategies?

**WeightedRoundRobin** applies a uniform default weight (100) to all servers unless overridden, while **InheritWeight** explicitly reads the `Weight` property value from each individual `Server` object. Both use circular selection algorithms, but InheritWeight allows per-server customization of traffic allocation, whereas WeightedRoundRobin treats servers equally unless specifically configured otherwise.

### How does the AutoSwitch strategy detect server failures?

The **AutoSwitch** strategy relies on the `ServerHealthChecker` class to perform periodic TCP pings against each configured server. It records response times in `Server.Latency` and increments failure counters when connections fail. When the active server's failure count exceeds the `MaxFailures` threshold, the selector automatically invokes `SwitchToBestServer()` to migrate traffic to the healthiest available endpoint.

### Can I use server auto-switching strategies with only one server configured?

While the strategies function technically with a single server, **load balancing strategies** (WeightedRoundRobin, InheritWeight) provide no benefit as only one endpoint exists. The **AutoSwitch** strategy can still monitor that single server's health, but automatic failover requires at least two configured servers to provide an alternative destination when the primary fails.

### Which strategy should I choose for maximum connection reliability?

For maximum reliability, select **AutoSwitch** (value 5). This high-availability mode continuously monitors server health through `ServerHealthChecker` and automatically fails over to the best-performing alternative when the current server becomes unresponsive. If you require load distribution across multiple healthy servers without automatic failover, use **WeightedRoundRobin** or **InheritWeight** instead.