# How to Configure Failover Thresholds and Cooldown Periods in MasterDnsVPN

> Learn to configure failover thresholds and cooldown periods in MasterDnsVPN to optimize stream resolver switching. Adjust settings via TOML, CLI, or programmatically.

- Repository: [Amin Mahmoudi/MasterDnsVPN](https://github.com/masterking32/MasterDnsVPN)
- Tags: how-to-guide
- Published: 2026-05-10

---

**MasterDnsVPN controls stream resolver switching via two parameters: `STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD` (default 2) and `STREAM_RESOLVER_FAILOVER_COOLDOWN` (default 2.5s), configurable via TOML, CLI flags, or programmatically through `SetStreamFailoverConfig`.**

MasterDnsVPN implements an intelligent stream failover mechanism to maintain DNS resolution stability when upstream resolvers fail. You can configure failover thresholds and cooldown periods in MasterDnsVPN through three distinct interfaces: configuration files, command-line arguments, or direct API calls. These settings determine how aggressively the client switches DNS resolver streams based on packet resend behavior.

## Understanding the Stream Failover Mechanism

The client balances DNS resolver streams using a **stream failover** system that monitors resend streaks. When a resolver repeatedly fails to acknowledge stream packets, the balancer switches traffic to an alternate resolver. Two critical parameters govern this behavior:

- **`STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD`**: The number of consecutive resend failures required to trigger a failover (default: `2`)
- **`STREAM_RESOLVER_FAILOVER_COOLDOWN`**: The minimum duration in seconds before another failover can occur for the same stream (default: `2.5`)

These parameters are defined in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go) as `StreamResolverFailoverResendThreshold` (int) and `StreamResolverFailoverCooldownSec` (float64) respectively.

## Internal Failover State Management

Each active stream maintains state through the `balancerStreamRouteState` struct defined in [`internal/client/balancer.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/balancer.go) at lines 49-54:

```go
type balancerStreamRouteState struct {
    PreferredResolverKey string
    ResendStreak         int
    LastFailoverAt       time.Time
}

```

When processing a packet marked as `Enums.PACKET_STREAM_RESEND`, the balancer increments `ResendStreak` and evaluates failover conditions at lines 34-40 in [`balancer.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/balancer.go):

```go
if state.ResendStreak < b.streamFailoverThreshold ||
   time.Since(state.LastFailoverAt) < b.streamFailoverCooldown {
     // remain on current resolver
}

```

If both the threshold is met and the cooldown has elapsed, the balancer executes `selectAlternateConnectionLocked` to switch resolvers and resets the state:

```go
state.PreferredResolverKey = replacement.Key
state.ResendStreak = 0
state.LastFailoverAt = time.Now()

```

## Configuration Methods

### TOML Configuration File

The most common method involves editing your [`client.toml`](https://github.com/masterking32/MasterDnsVPN/blob/main/client.toml) file. Add or modify these entries under the `[client]` section:

```toml
STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD = 3
STREAM_RESOLVER_FAILOVER_COOLDOWN = 5.0

```

The TOML parser in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go) automatically clamps values to safe ranges: thresholds between 1-128 and cooldowns between 0.1-120 seconds.

### Command-Line Flags

Override configuration file values at runtime using flag bindings created in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go) via `NewClientConfigFlagBinder`:

```bash
masterdnsvpn-client \
    --stream-resolver-failover-resend-threshold=4 \
    --stream-resolver-failover-cooldown=10.0

```

Command-line arguments take precedence over file-based configuration.

### Programmatic API

When embedding the MasterDnsVPN client library, call `SetStreamFailoverConfig` directly on the balancer instance. This method validates inputs (minimum threshold: 1, minimum cooldown: 1s) and stores them atomically:

```go
func (b *Balancer) SetStreamFailoverConfig(threshold int, cooldown time.Duration) {
    if threshold < 1 { threshold = 1 }
    if cooldown <= 0 { cooldown = time.Second }
    b.mu.Lock()
    b.streamFailoverThreshold = threshold
    b.streamFailoverCooldown = cooldown
    b.mu.Unlock()
}

```

During client initialization in [`internal/client/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/client.go) at lines 273-274, the system propagates configuration values:

```go
c.balancer.SetStreamFailoverConfig(
    cfg.StreamResolverFailoverResendThreshold,
    time.Duration(cfg.StreamResolverFailoverCooldownSec*float64(time.Second)))

```

## Practical Configuration Examples

### Example 1: High-Stability Tuning

For resolver pools with intermittent latency, increase tolerance to prevent premature switching:

```toml

# masterdnsvpn_client.toml

STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD = 5
STREAM_RESOLVER_FAILOVER_COOLDOWN = 15.0

```

This configuration allows five consecutive resend failures and enforces a 15-second cooldown between switches.

### Example 2: Aggressive Failover via CLI

For low-latency applications requiring rapid recovery:

```bash
masterdnsvpn-client \
    --config=client.toml \
    --stream-resolver-failover-resend-threshold=1 \
    --stream-resolver-failover-cooldown=1.0

```

### Example 3: Embedded Client with Custom Policy

```go
package main

import (
    "time"
    "github.com/masterking32/MasterDnsVPN/internal/client"
    "github.com/masterking32/MasterDnsVPN/internal/logger"
)

func main() {
    log := logger.New(logger.InfoLevel)
    bal := client.NewBalancer(client.BalancingLeastLoss, log)
    
    // Require 8 resends, 20-second cooldown
    bal.SetStreamFailoverConfig(8, 20*time.Second)
    
    // Proceed with connection setup...
}

```

## Summary

- **Failover thresholds** in MasterDnsVPN determine how many consecutive stream packet resends (`STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD`) must occur before switching resolvers.
- **Cooldown periods** (`STREAM_RESOLVER_FAILOVER_COOLDOWN`) prevent rapid-fire resolver switching by enforcing a minimum delay between failovers for the same stream.
- Configure these parameters via **TOML files**, **CLI flags**, or the **`SetStreamFailoverConfig`** API method in [`internal/client/balancer.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/balancer.go).
- The `balancerStreamRouteState` struct tracks per-stream state including the current resolver key, resend streak count, and last failover timestamp.
- All configuration methods enforce minimum safety bounds: thresholds must be at least 1, cooldowns at least 1 second.

## Frequently Asked Questions

### What is the minimum value for the failover threshold?

The minimum value for `STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD` is `1`. The `SetStreamFailoverConfig` function in [`internal/client/balancer.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/balancer.go) automatically clamps any value below 1 to 1, ensuring that at least one resend failure is required before considering a failover.

### How does the cooldown period prevent resolver flapping?

The cooldown period prevents **resolver flapping** by requiring that `time.Since(state.LastFailoverAt)` exceed `b.streamFailoverCooldown` before executing another switch. As implemented in [`balancer.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/balancer.go) lines 34-40, this check ensures that even if resend streaks continue to accumulate, the balancer cannot switch resolvers more frequently than the configured interval, stabilizing connections to temporarily degraded upstreams.

### Can I disable stream failover entirely?

You cannot completely disable stream failover through configuration, but you can effectively neutralize it by setting `STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD` to a high value (maximum 128) and `STREAM_RESOLVER_FAILOVER_COOLDOWN` to the maximum 120 seconds. The validation logic in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go) enforces these upper bounds to prevent infinite accumulation of failover state.

### Where are the default failover values defined?

Default values are defined in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go) where the `ClientConfig` struct initializes `StreamResolverFailoverResendThreshold` to `2` and `StreamResolverFailoverCooldownSec` to `2.5`. These defaults are applied when the TOML file lacks explicit values or when environment-specific overrides are not provided.