This episode covers scale: limiting clients with max-clients, controlling connection rate with connect-freq and rate limiting, running multiple OpenVPN instances, and load balancing with learn-address and round-robin DNS.

Your VPN server is healthy for ten users. Now imagine a hundred, five hundred, or more. OpenVPN handles thousands of connections in a single process, but there are practical limits and risks: a surge of connections can exhaust handshake CPU, and a single server means a single point of failure.
Episode 11 covers connection broker and scalability. You will learn to limit resources with --max-clients, control connection rate with --connect-freq and rate limiting, run multiple OpenVPN instances to serve different segments, and distribute load with learn-address and round-robin DNS.
The end goal is simple: a VPN infrastructure that grows without pain, stays responsive at traffic peaks, and doesn't collapse when one node fails.
The first parameter you should control is the number of concurrent connections. The max-clients directive sets an upper bound on clients that can connect to a single instance:
max-clients 200max-clients 200 causes the 201st connection to be rejected. This protects the daemon from running out of file descriptors and protects the network from one overwhelmed instance. The ideal number depends on the server's CPU capacity and bandwidth.
Repeated reconnects — due to client errors or attacks — can exhaust handshake resources. --connect-freq limits the number of connect attempts per minute per client:
connect-freq 20 60connect-freq 20 60 allows at most 20 attempts within a 60-second window from the same origin address. Beyond that, further attempts are rejected. This prevents a single broken client or attacker from clogging the handshake process.
For more granular protection, combine with limits at the firewall or service level:
iptables -A INPUT -p udp --dport 1194 -m hashlimit \
--hashlimit-above 30/sec --hashlimit-mode srcip \
--hashlimit-name openvpn -j DROPThis iptables rule with hashlimit rejects connections exceeding 30 packets per second from a single source IP. Use this rule as the first layer, then let connect-freq handle the OpenVPN-specific logic. Layered patterns like this are what's called defense-in-depth.
When one instance isn't enough, you don't have to move everything into a single big daemon. OpenVPN supports multiple instances on one host, each with a different port or protocol:
systemctl enable openvpn-server@udp1194
systemctl enable openvpn-server@tcp443
systemctl start openvpn-server@udp1194
systemctl start openvpn-server@tcp443The udp1194 instance serves ordinary clients over UDP, while tcp443 serves clients trapped behind networks that only allow HTTPS. Each instance has its own configuration file and its own subnet, so load and failure zones are separated.
Separating instances brings three advantages: failure isolation — one crashed instance doesn't take down the others, policy segmentation — different instances can use different CAs and policies, and linear scalability — capacity grows simply by adding instances.
Note that each instance still must be guarded with the same resource limits: max-clients applies per instance, so total capacity is the sum of all instances. Likewise, monitoring must cover all instances, not just the first — a theme covered in episode 19.
When multiple instances share one VPN subnet, address conflicts between instances can occur. The learn-address directive calls a script every time an address changes:
learn-address /etc/openvpn/scripts/learn-address.shThe learn-address.sh script receives three arguments: the operation (add, update, delete), the address, and the common name. This script is often used to synchronize routing tables between instances or to reject duplicate addresses.
The cheapest way to distribute clients is DNS with multiple A records for one name:
vpn.example.com A 203.0.113.10
vpn.example.com A 203.0.113.11
vpn.example.com A 203.0.113.12Clients doing a lookup receive the addresses in different orders, so the load gets spread. Its drawback: round-robin DNS knows nothing about server health, so a client can be directed to a server that's having problems.
For health-aware distribution, put a broker in front of many instances. learn-address and the management interface from episode 8 can be used by the broker to redirect clients to healthy servers. This combination will be deepened in episode 17 about multi-server and clusters.
Key takeaways:
max-clients limits concurrent connections per instance.connect-freq limits the connect attempt rate from one source.learn-address synchronizes addresses between instances via script.In the next episode, episode 12, we will discuss configuration management and automation — writing template-based configurations, hardening systemd units, the env-file pattern for secrets, and automatic provisioning with Ansible and community scripts like openvpn-install.sh. After this episode, your VPN configuration can be reproduced with a single command.