skip to content

Stick Tables, Persistence & Rate Limiting

Stick tables are HAProxy's differentiator: an in-memory keyed store I can track per source IP, header or cookie, holding counters like `http_req_rate` and sticking a client to one server. I get asked it because it is the same primitive behind sticky sessions, per-client throttling and slow-scraper defence, and because `peers` replication across instances is a genuinely tricky follow-up.

on this pageshow

questions

6

You need an HAProxy frontend to answer 429 to any client IP that exceeds 100 requests in 10 seconds. Walk through the `stick-table`, `http-request track-sc0` and `http-request deny` lines required, and explain what order they must appear in and why.

level: middleimportance: must knowfreq 65%

basics

~20 s

Declare a table storing http_req_rate(10s), track each request against it with http-request track-sc0 src, then deny with http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }. The track rule must come first, because the deny rule reads the counter that tracking populates.

open as a page

An HAProxy backend contains the lines `stick-table type ip size 1m expire 30m` and `stick on src`. What do those two lines make the backend do with a returning client, and what happens once an entry expires?

level: juniorimportance: should knowfreq 45%

basics

~20 s

HAProxy keeps one in-memory entry per client IP recording which server that IP was sent to, and routes the same IP back to that server on later requests. After 30 minutes with no match the entry is purged and the balance algorithm chooses again.

open as a page

In HAProxy, what do the `size`, `expire` and `store` parameters of a `stick-table` line control, and what happens to new clients once the table is full?

level: middleimportance: should knowfreq 48%

basics

~20 s

size is the maximum number of entries, expire the idle timeout per entry, and store the list of counters each entry carries, with the measurement window declared inside the counter. When the table is full HAProxy purges the oldest entries to make room, unless nopurge is set.

open as a page

Two HAProxy nodes sit behind a round-robin DNS record and each enforces a per-source-IP request limit using its own stick table. What goes wrong, and what does adding an HAProxy `peers` section change?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Each node counts only the traffic it sees, so a client spread across both nodes gets roughly double the intended limit, and a client that moves nodes loses its stickiness. A peers section replicates table entries between nodes asynchronously, giving one shared view rather than two independent ones.

open as a page

Once an HAProxy stick-table counter marks a client as abusive, you can respond with `http-request deny`, `http-request tarpit` or `http-request silent-drop`. What does each do to the client and to your own resources?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

deny answers immediately with an error and frees the connection, tarpit holds the request for the tarpit timeout before answering and ties up a session slot meanwhile, and silent-drop discards the connection without telling the client, costing HAProxy least but leaving state on every device in between.

open as a page