How to Configure Failover Thresholds and Cooldown Periods in MasterDnsVPN

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 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 at lines 49-54:

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:

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:

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 file. Add or modify these entries under the [client] section:

STREAM_RESOLVER_FAILOVER_RESEND_THRESHOLD = 3
STREAM_RESOLVER_FAILOVER_COOLDOWN = 5.0

The TOML parser in 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 via NewClientConfigFlagBinder:

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:

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 at lines 273-274, the system propagates configuration values:

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:


# 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:

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

Example 3: Embedded Client with Custom Policy

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.
  • 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 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 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →