Learn HAProxy - Advanced Configuration & Runtime API
Episode 9 of 23

Learn HAProxy - Advanced Configuration & Runtime API

This episode unlocks dynamic control of HAProxy: changing configuration at runtime through the stats socket, setting server weight and draining without restart, and using stick tables for rate limiting, authentication, and security.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Restarting HAProxy disrupts in-flight connections. The good news: most changes can be made without a restart through the runtime API — a set of commands sent over the stats socket.

Episode 9 covers those three dynamic powers: runtime configuration, server management like weight and draining, and stick tables, the foundation of rate limiting and protection. By the end of the episode, you'll be able to manage HAProxy serving real traffic without fear.

Runtime API and Dynamic Configuration

Enabling Admin Level

The runtime API needs a stats socket with admin level:

Admin-level stats socket
global
    stats socket /run/haproxy.sock mode 660 level admin
    stats timeout 30s

The stats socket /run/haproxy.sock mode 660 level admin directive creates a socket with admin access. Make sure the socket's owner and permissions are correct so only authorized processes can use it.

Sending Runtime Commands

All commands are sent as text over the socket:

A few basic runtime commands
echo "show info" | socat stdio /run/haproxy.sock
echo "show servers state" | socat stdio /run/haproxy.sock
echo "help" | socat stdio /run/haproxy.sock

echo "show info" | socat stdio /run/haproxy.sock shows process information, and echo "help" | socat stdio /run/haproxy.sock prints the list of supported commands. Get in the habit of checking help first whenever your HAProxy version changes.

Managing Servers at Runtime

Changing Server Weight

Server weight can be adjusted without a reload. This is useful when you want to gradually pull traffic away from a server:

Change server weight
echo "set weight web_back/web1 10" | socat stdio /run/haproxy.sock
echo "set weight web_back/web2 50" | socat stdio /run/haproxy.sock

The command echo "set weight web_back/web1 10" | socat stdio /run/haproxy.sock lowers web1's weight to 10. Traffic slowly shifts to web2 without breaking existing connections.

Draining and Maintenance

To take a server out of rotation smoothly, use DRAIN mode, then MAINT:

Drain a server before maintenance
echo "set server web_back/web1 state drain" | socat stdio /run/haproxy.sock
echo "set server web_back/web1 state maint" | socat stdio /run/haproxy.sock

set server web_back/web1 state drain stops new traffic to the server but keeps serving existing connections. Once it's safe, state maint takes the server fully down for maintenance.

Seeing Changes in Action

Verify server state after runtime commands:

View server state
echo "show servers state web_back" | socat stdio /run/haproxy.sock

echo "show servers state web_back" | socat stdio /run/haproxy.sock shows each server's state in a CSV format that's easy for scripts to parse.

Stick Tables for Security

Stick Table Anatomy

A stick table is a fast in-memory key-value store, whose primary key is usually an IP or session:

Stick table definition for rate limiting
frontend web_front
    bind *:80
    mode http
 
    stick-table type ip size 100k expire 30s \
        store http_req_rate(10s)
    http-request track-sc0 src
    default_backend web_back

The stick-table type ip size 100k expire 30s store http_req_rate(10s) directive creates a table storing the request rate per 10 seconds for each IP, with 100,000 entries maximum. http-request track-sc0 src ties the client IP to the stick table.

Reading Stick Table Data

The stick table contents can be viewed through the runtime API:

Show stick table contents
echo "show table web_front" | socat stdio /run/haproxy.sock

echo "show table web_front" | socat stdio /run/haproxy.sock shows every entry along with its request rate value. From here you can see which IPs are requesting the most — the raw material for anomaly detection.

General Purpose Counters

Stick tables also provide a versatile gpc0 counter that can be used for flags or bans:

gpc0 counter for bans
backend api_back
    stick-table type ip size 100k expire 10m \
        store gpc0_rate(10m)
    http-request track-sc0 src
    http-request deny if { sc0_inc_gpc0(api_back) gt 0 }

The line http-request deny if { sc0_inc_gpc0(api_back) gt 0 } increments the counter and rejects the request as soon as the counter is greater than zero. This is the basic pattern for a temporary blocklist, covered in depth in episode 10.

Closing

Episode 9 changes the way you operate HAProxy: from static to dynamic. The runtime API for changes without downtime, smooth server management, and stick tables as operational memory for security.

Key takeaways:

  • An admin-level stats socket opens the runtime API.
  • set weight and set server state manage servers without reloads.
  • DRAIN mode pulls traffic slowly; MAINT takes servers down for maintenance.
  • Stick tables store IP-based state with a timeout.
  • The gpc0 counter is the foundation for bans and rate limiting.

In the next episode we'll build rate limiting & protection on top of stick tables — limiting connections and request rates, mitigating brute force, and rejecting requests with deny rules.