# How to Optimize Worker Thread Counts for High-Throughput Scenarios in MasterDnsVPN

> Boost MasterDnsVPN throughput by optimizing worker thread counts. Learn how to align UDPReaders, DNSRequestWorkers, and DeferredSessionWorkers with your CPU cores for maximum performance.

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

---

**Optimize MasterDnsVPN performance by aligning UDPReaders, DNSRequestWorkers, and DeferredSessionWorkers with your CPU core count and I/O patterns to maximize parallel packet processing.**

MasterDnsVPN uses a multi-pool goroutine architecture to parallelize UDP packet ingestion, DNS resolution, and deferred SOCKS5 session handling. Tuning these worker thread counts is the primary mechanism for scaling the server to handle high-throughput scenarios such as thousands of simultaneous clients or extreme DNS query rates.

## Understanding the Worker Pool Architecture

The server distributes work across four distinct configurable pools. Each pool feeds from specific channels and has hardcoded safety limits to prevent resource exhaustion.

### UDP Readers (`UDPReaders`)

The **UDPReaders** configuration controls how many goroutines read raw packets from the `net.UDPConn` socket. These readers pull packets and push them onto a shared request channel for downstream processing.

- **Default**: `4`
- **Location**: [`internal/udpserver/server_runtime.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/server_runtime.go) in `func (s *Server) startUDPReaders`
- **Best practice**: Scale this to match or slightly exceed your physical CPU count when running on multi-core servers.

### DNS Request Workers (`DNSRequestWorkers`)

**DNSRequestWorkers** consume items from the request channel and perform the actual resolution work, including cache lookups and upstream forwarding. They write responses directly back to the socket.

- **Default**: `8`
- **Location**: [`internal/udpserver/server_runtime.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/server_runtime.go) in `func (s *Server) startDNSWorkers`
- **Key insight**: These workers are CPU-intensive; blocking on upstream DNS latency means more workers can keep cores busy.

### Deferred Session Workers (`DeferredSessionWorkers`)

When a SOCKS5 tunnel request encounters a slow or temporarily unavailable upstream, the **deferred session processor** queues the task. `DeferredSessionWorkers` handle this deferred establishment, each with its own bounded queue.

- **Default**: `4` workers, `4096` queue limit (`DeferredSessionQueueLimit`)
- **Location**: [`internal/udpserver/deferred_session.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/deferred_session.go) in `newDeferredSessionProcessor`
- **Hard cap**: The source code automatically clamps worker counts to a maximum of `64`:

```go
if workerCount > 64 {
    workerCount = 64 // lines 84-85 of deferred_session.go
}

```

### Client-Side Workers (`ClientMaxRxTxWorkers`)

On the client side, this setting limits parallel RX/TX workers for data streams.

- **Default**: `255`
- **Location**: [`internal/vpnproto/session_accept.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/session_accept.go) (encoded in the session-handshake payload)
- **Recommendation**: Reduce to `8-16` for laptops to prevent local CPU saturation.

## Runtime Safety Limits and Validation

The server validates worker counts at startup to prevent misconfiguration. In [`internal/udpserver/deferred_session.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/deferred_session.go) (lines 50-86), the `newDeferredSessionProcessor` function enforces:

```go
if workerCount <= 0 {
    workerCount = 1
}
if workerCount > 64 {
    workerCount = 64
}

```

If you configure values outside these ranges, the server automatically clamps them and logs a warning via `deferredSessionProcessor.maybeLogPressureLocked`.

## High-Throughput Configuration Strategies

Use the following targeted adjustments based on your hardware and traffic patterns:

- **CPU-bound deployments (32+ cores)**: Increase `UDPReaders` and `DNSRequestWorkers` to match `runtime.NumCPU()` or slightly higher. A useful rule of thumb is **`workers ≈ number_of_cores * 1.5`**.
- **I/O-bound scenarios (high upstream latency)**: Raise `DeferredSessionWorkers` toward the 64-worker cap and increase `DeferredSessionQueueLimit` to `8192` or higher. This reduces wait time for pending SOCKS5 connections.
- **Memory-constrained environments**: Keep `DeferredSessionQueueLimit` modest (e.g., `1024`) and avoid excessive `DNSRequestWorkers`. Each queue slot consumes memory, and thousands of pending jobs can cause OOM conditions.
- **Burst traffic patterns**: Temporarily double `UDPReaders` and `DNSRequestWorkers`. The deferred processor applies back-pressure when `workerPending < 16 && sessionPending < p.sessionPendingCap`, preventing memory spikes while absorbing peaks.

## Implementing Configuration Changes

All worker counts are configurable via TOML or command-line flags through `ServerConfigFlagBinder` in [`internal/config/server.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/server.go) (lines 108-112).

**TOML configuration** ([`server_config.toml`](https://github.com/masterking32/MasterDnsVPN/blob/main/server_config.toml)):

```toml
UDP_READERS = 8
DNS_REQUEST_WORKERS = 16
DEFERRED_SESSION_WORKERS = 8
DEFERRED_SESSION_QUEUE_LIMIT = 8192

```

**Command-line flags**:

```bash
./masterdnsvpn-server -udp-readers=8 -dns-request-workers=16 -deferred-session-workers=8

```

## Benchmarking Your Optimizations

Validate throughput changes using the built-in benchmark utility:

```bash
go run ./scripts/bench -udp-readers=8 -dns-workers=16

```

Adjust flags according to the benchmark's CLI options (see `scripts/bench` README) to measure QPS and latency improvements.

## Summary

- **MasterDnsVPN** uses separate pools for UDP reading, DNS resolution, and deferred SOCKS5 sessions.
- **Hard limits** prevent runaway goroutine creation: `64` max for deferred workers, `255` for client Rx/Tx.
- **Configuration** happens via [`internal/config/server.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/server.go) using TOML files or CLI flags.
- **Scaling rule**: Set UDP and DNS workers to approximately `1.5x` your CPU core count for CPU-bound workloads.
- **I/O optimization**: Increase deferred workers and queue limits when handling high-latency upstream connections.

## Frequently Asked Questions

### What are the default worker thread counts in MasterDnsVPN?

The server defaults to `4` UDPReaders, `8` DNSRequestWorkers, and `4` DeferredSessionWorkers with a queue limit of `4096`. Client configurations default `ClientMaxRxTxWorkers` to `255`.

### Why is there a hard limit of 64 deferred session workers?

The limit prevents runaway goroutine creation under misconfiguration or attack conditions. Values exceeding `64` are automatically clamped to `64` in [`internal/udpserver/deferred_session.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/deferred_session.go) lines 84-85.

### How do I choose between increasing DNS workers versus deferred session workers?

Increase **DNSRequestWorkers** when your bottleneck is CPU processing or cache misses. Increase **DeferredSessionWorkers** when you observe delays in SOCKS5 tunnel establishment due to slow upstream I/O.

### Can client-side worker counts impact server throughput?

Yes. The `ClientMaxRxTxWorkers` value (sent in the session handshake per [`internal/vpnproto/session_accept.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/session_accept.go)) determines how aggressively the client multiplexes streams. Over-provisioning this on low-powered clients can saturate local CPUs and reduce effective throughput without benefiting the server.