TCP load balancing is a solved problem — HAProxy, Nginx, and Envoy dominate the space. But UDP load balancing is a different beast. UDP is connectionless, stateless, and has no handshake to track. This makes UDP load balancing fundamentally different from TCP, requiring specialized tools that understand session persistence without connection state. This guide compares three open-source UDP load balancing solutions.
Why UDP Load Balancing Matters
Many critical services run over UDP and need load balancing for scalability and high availability:
- DNS resolvers — Distribute queries across multiple Unbound, BIND, or PowerDNS instances
- Syslog collectors — Balance incoming syslog traffic across multiple log aggregation nodes
- RADIUS/FreeRADIUS — Distribute authentication requests across multiple RADIUS servers
- NTP servers — Balance time synchronization requests across multiple NTP daemons
- Game servers — Distribute player connections across multiple game server instances
- VoIP/SIP — Balance SIP signaling and RTP media streams across multiple PBX instances
- SNMP traps — Distribute trap traffic across multiple trap receivers
- Streaming protocols — Balance RTMP, QUIC, and WebRTC traffic
For TCP and HTTP load balancing, see our advanced load balancer guide and BGP routing guide for anycast-based approaches. If you need API-level load balancing, our API gateway comparison covers Layer 7 routing.
HAProxy UDP Mode (Frontend/Backend UDP)
HAProxy is primarily known as a TCP/HTTP load balancer, but since version 2.4, it has native UDP load balancing support through mode udp frontends and backends. This makes HAProxy a compelling option if you’re already using it for TCP/HTTP traffic.
Key Features
- Native UDP mode (HAProxy 2.4+)
- Round-robin, leastconn, source, and uri balancing algorithms
- Health checks via UDP probes
- Session persistence via source IP hashing
- Statistics web interface
- Rate limiting and connection limiting
- Lua scripting for custom logic
- Active health checks with configurable intervals
Installation
| |
Configuration
| |
Docker Compose Deployment
| |
HAProxy’s UDP mode is ideal if you already run HAProxy for TCP/HTTP traffic. You get a unified configuration, familiar management tools, and the robust HAProxy ecosystem. The main limitation is that UDP health checks are limited — HAProxy can send a probe and expect a response, but many UDP services don’t have a built-in “health check” protocol.
Pen
Pen is a lightweight UDP (and TCP) load balancer written in C. It’s been around since 2001 and is designed for simplicity — a single binary with a straightforward command-line interface. Despite its age, it remains effective for UDP load balancing use cases.
Key Features
- UDP and TCP load balancing
- Round-robin and source-based balancing
- Built-in health checking (UDP ping)
- Session persistence via client IP
- Very low resource usage (~2MB memory)
- Simple CLI configuration (no config file needed)
- Daemon mode with PID file management
- Supports IPv4 and IPv6
Installation
| |
Configuration
Pen is configured entirely via command-line arguments:
| |
Command-line flags:
-f— Run in foreground (remove for daemon mode)-u— UDP mode-r— Round-robin balancing (default is source-based)-s— Source IP persistence-d— Daemon mode-p— PID file path-H— Health check string to send
Docker Deployment
| |
Pen is the simplest possible UDP load balancer. Its command-line-only configuration is both a strength (easy to understand, no config file syntax to learn) and a weakness (no hot reload, no structured config management). It’s best for straightforward UDP balancing where you need minimal overhead.
Balance
Balance is another lightweight TCP/UDP load balancer written in C. Similar in philosophy to Pen, it uses a simple command-line interface and is designed for embedded systems and resource-constrained environments. It supports TCP, UDP, and even SCTP load balancing.
Key Features
- UDP, TCP, and SCTP load balancing
- Round-robin, weighted, and hash-based balancing
- TCP/UDP health checking
- Session persistence via source IP or port hashing
- Extremely low resource usage (~1MB memory)
- Simple CLI configuration
- Built-in HTTP status page
- Supports transparent proxy mode
Installation
| |
Configuration
Like Pen, Balance is configured via command-line arguments:
| |
Command-line flags:
-u— UDP mode-r— Round-robin-w— Weighted round-robin (append=weightto server address)-H— Hash-based (source IP)-d— Daemon mode-c— Control/status port
Docker Deployment
| |
Balance is very similar to Pen in philosophy but offers a few additional features: weighted round-robin balancing, a built-in HTTP status page, and SCTP support. It’s slightly more feature-rich while maintaining the same low resource footprint.
Feature Comparison
| Feature | HAProxy UDP | Pen | Balance |
|---|---|---|---|
| UDP Mode | Native (v2.4+) | Yes | Yes |
| TCP Mode | Yes | Yes | Yes |
| Config Method | Config file | CLI args | CLI args |
| Hot Reload | Yes | No | No |
| Health Checks | UDP probes | UDP ping | UDP/TCP probes |
| Balancing Algorithms | 7+ (rr, source, leastconn, uri, hdr, etc.) | Round-robin, source | Round-robin, weighted, hash |
| Session Persistence | Source hash, cookie, table | Source IP | Source IP, port hash |
| Statistics Interface | Web UI (built-in) | CLI (penctl) | HTTP status page |
| Rate Limiting | Yes | No | No |
| Lua Scripting | Yes | No | No |
| Resource Usage | Medium (~20MB) | Very Low (~2MB) | Very Low (~1MB) |
| IPv6 Support | Yes | Yes | Yes |
| Active Development | Yes (active) | Minimal | Minimal |
| Learning Curve | Moderate (config syntax) | Easy (CLI only) | Easy (CLI only) |
Choosing the Right Tool
Use HAProxy UDP mode when:
- You already run HAProxy for TCP/HTTP traffic
- You need advanced features: health checks, rate limiting, Lua scripting
- You want a web-based statistics dashboard
- You need hot reload configuration without dropping connections
- Your team is already familiar with HAProxy configuration syntax
Use Pen when:
- You need the simplest possible UDP load balancer
- Resource constraints are tight (embedded systems, small VMs)
- You want zero-config-file overhead (CLI-only setup)
- Your load balancing needs are straightforward (round-robin or source-based)
Use Balance when:
- You need weighted round-robin (different traffic ratios per server)
- You want a built-in HTTP status page for monitoring
- You need SCTP load balancing alongside UDP
- You prefer CLI configuration but want more options than Pen provides
Performance Tuning
HAProxy UDP Optimization
| |
Pen Tuning
| |
Kernel UDP Buffer Tuning
| |
FAQ
Why can’t I use Nginx for UDP load balancing?
Nginx does support UDP load balancing via the stream module (stream { upstream dns_servers { ... } }). However, this guide focused on dedicated UDP load balancers (HAProxy UDP mode, Pen, Balance) because they offer more UDP-specific features. Nginx’s UDP support is functional but limited compared to HAProxy’s richer feature set or Pen/Balance’s simplicity. If you’re already running Nginx, the stream module is a perfectly valid fourth option.
How does session persistence work with UDP?
Since UDP is connectionless, there’s no “session” to track in the TCP sense. Session persistence for UDP typically means: all packets from the same source IP go to the same backend server. This is called “source IP hashing” and is critical for protocols like DNS (where a client expects responses from the same server it queried) and RADIUS (where authentication state is server-local).
Can these tools handle QUIC/HTTP3 traffic?
HAProxy has native QUIC support (since 2.8) with HTTP/3 termination. Pen and Balance operate at the raw UDP level and can forward QUIC packets, but they cannot inspect or terminate QUIC connections. For QUIC load balancing with HTTP/3 awareness, HAProxy is the only option among these three.
What about anycast as a UDP load balancing method?
Anycast (advertising the same IP from multiple locations via BGP) is an excellent UDP load balancing technique — especially for DNS. It works at the network layer and requires no proxy software. However, anycast requires BGP configuration and multiple network locations. Our BGP routing guide covers BGP setup. For single-site deployments, a software load balancer is more practical.
How do I monitor UDP load balancer health?
HAProxy provides a built-in statistics web interface (typically on port 8404) with per-backend connection counts, response times, and health status. Pen has the penctl CLI tool for querying runtime status. Balance provides an HTTP status page on its control port. All three can export metrics to Prometheus via sidecar exporters or built-in endpoints.
Is UDP load balancing stateful or stateless?
It depends on the tool. Pen and Balance with source IP hashing are stateless — they compute the backend from the source IP using a hash function. HAProxy can maintain connection tables for stateful tracking (tracking which source IP is mapped to which backend). For most UDP use cases, stateless source hashing is sufficient and more resilient to restarts.
What’s the maximum throughput for these tools?
On modern hardware: HAProxy can handle 500,000+ UDP packets/sec with proper tuning. Pen can handle 200,000+ packets/sec with minimal CPU. Balance is similar to Pen. The bottleneck is usually the backend servers, not the load balancer itself. For extremely high-throughput scenarios (millions of packets/sec), consider kernel-space solutions like XDP/eBPF (covered in our XDP/eBPF network tools guide).