Hi,
HAProxy 3.4-dev6 was released on 2026/03/05. It added 110 new commits
after version 3.4-dev5.
The last two weeks have been active in various areas including bug fixes.
We're also going to issue stable releases soon I think.
Regarding feature improvements, we have this:
- support for backend deletion ("del backend" on the CLI). In short, a
backend that is no longer referenced anywhere, that doesn't have any
server anymore nor any connection can now be unpublished (it's no
longer found by "use_backend" rules) and deleted. The typical approach
is:
1) for all servers of backend $BKNAME:
disable server $BKNAME/...
shutdown sessions server $BKNAME/...
wait 10s srv-removable $BKNAME/...
del server $BKNAME/...
2) then delete the backend:
unpublish backend $BKNAME
experimental-mode on
wait 10s be-removable $BKNAME
del backend $BKNAME
There may be some remaining rare corner cases where it can take a long
time to delete a backend or where it's not yet supported: active
connection to a local applet such as the cache, which currently we can
not kill, or use of QUIC on the backend, for which connections are not
listed yet. But these are marginal limitations that may be addressed
before the final release depending on how testing goes. Please do test
and report issues. It would be great if we can drop the experimental
status for the release.
- HTTP version reporting: we've long had various ways to report HTTP
versions, via req.ver, capture.req.ver, fc_major etc for the request,
and their equivalents for the response. There used to be good reasons
for this originally, but it's no longer fun to see how difficult it
can be to have a correct version in logs. This comes from the fact
that H2/H3 do not convey any version string and that for H1 it's in
the message that's possibly no longer in the buffer, hence has to be
captured during parsing. In short, the version is retrieved at different
layers depending on the protocol version. This has been entirely
refactored so that req.ver/res.ver always report the proper version in
the major.minor format (when the version is valid), and that capture.*
returns the same with "HTTP/" prepended for compatibility purposes. In
addition, requests and responses to/from applets will now reflect the
other side's version since internally there is no version. E.g. logging
the version of the response from the cache will report the same version
as the mux it came from, e.g. 2.0 if connected to mux-h2, instead of 1.1
previously. Similarly the httpclient's logs will now reflect the real
version used to reach the remote server.
- stats counters: on large systems, the contention caused by incrementing
the extra counters for each request were starting to cost a lot, so they
were now split by thread group internally. The change is not visible
outside, as numbers reported in stats when "stats show-modules" is
enabled remain the same (they're now aggregated). In addition, some
remaining shared counters were only used to calculate maximums that are
reported on the stats page (req/s max, sess/s max etc), which the vast
majority of users no longer care about. A new stats directive,
"calculate-max-counters", allows to disable them and at the same time
avoid updating such internal counters used solely for this. All these
updates showed performance gains of 16-20% on HTTP/1.
- debugging: stream dumps (in show threads or watchdog output) will do a
better job at displaying the rule currently being evaluated as well as
the current filter.
- some internal changes to the way ALPN is used with QUIC on the backend,
to make it more reliable in the event the cached entry changes during
the connection setup.
- H2: certain request errors could lead to a log being emitted for each
request, making it a big source of log pollution. Some only act at the
connection level and are not necessarily desirable either in exposed
environments. A new global directive, "tune.h2.log-errors" appeared to
decide if logs should be emitted for stream errors, connection errors,
or never.
- the rest is essentially cleanups and bug fixes.
I know that there are still patches pending for review on the list, sorry
for that, but the time spent analysing an increase of bug reports left too
little to review extra code. And don't get me wrong, it's good to receive
bug reports, it proves users are testing and this is super helpful! So if
you have patches pending, please just be patient (and possibly ping a
maintainer of the area you're touching, after a git log on the same file).
Please find the usual URLs below :
Site index : https://www.haproxy.org/
Documentation : https://docs.haproxy.org/
Wiki : https://github.com/haproxy/wiki/wiki
Discourse : https://discourse.haproxy.org/
Slack channel : https://slack.haproxy.org/
Issue tracker : https://github.com/haproxy/haproxy/issues
Q&A from devs : https://github.com/orgs/haproxy/discussions
Sources : https://www.haproxy.org/download/3.4/src/
Git repository : https://git.haproxy.org/git/haproxy.git/
Git Web browsing : https://git.haproxy.org/?p=haproxy.git
Changelog : https://www.haproxy.org/download/3.4/src/CHANGELOG
Dataplane API :
https://github.com/haproxytech/dataplaneapi/releases/latest
Pending bugs : https://www.haproxy.org/l/pending-bugs
Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs
Code reports : https://www.haproxy.org/l/code-reports
Latest builds : https://www.haproxy.org/l/dev-packages
Willy
---
Complete changelog :
Amaury Denoyelle (40):
BUG/MINOR: proxy: detect strdup error on server auto SNI
BUG/MINOR: server: set auto SNI for dynamic servers
BUG/MINOR: server: enable no-check-sni-auto for dynamic servers
BUG/MINOR: quic: fix counters used on BE side
MINOR: quic: add BUG_ON() on half_open_conn counter access from BE
BUG/MINOR: quic/h3: display QUIC/H3 backend module on HTML stats
MINOR: ncbmbuf: improve itbmap_next() code
MINOR: proxy: improve code when checking server name conflicts
MINOR: promex: test applet resume in stress mode
BUG/MINOR: promex: fix server iteration when last server is deleted
BUG/MINOR: proxy: add dynamic backend into ID tree
MINOR: proxy: convert proxy flags to uint
MINOR: server: refactor srv_detach()
MINOR: proxy: define a basic "del backend" CLI
MINOR: proxy: define proxy watcher member
MINOR: stats: protect proxy iteration via watcher
MINOR: promex: use watcher to iterate over backend instances
MINOR: lua: use watcher for proxies iterator
MINOR: proxy: add refcount to proxies
MINOR: proxy: rename default refcount to avoid confusion
MINOR: server: take proxy refcount when deleting a server
MINOR: lua: handle proxy refcount
MINOR: proxy: prevent backend removal when unsupported
MINOR: proxy: prevent deletion of backend referenced by config elements
MINOR: proxy: prevent backend deletion if server still exists in it
MINOR: server: mark backend removal as forbidden if QUIC was used
MINOR: cli: implement wait on be-removable
MINOR: proxy: add comment for defaults_px_ref/unref_all()
MEDIUM: proxy: add lock for global accesses during proxy free
MEDIUM: proxy: add lock for global accesses during default free
MINOR: proxy: use atomic ops for default proxy refcount
MEDIUM: proxy: implement backend deletion
REGTESTS: add a test on "del backend"
REGTESTS: complete "del backend" with unnamed defaults ref free
BUG/MINOR: hlua: fix return with push nil on proxy check
MINOR: quic: use signed char type for ALPN manipulation
MINOR: quic/h3: reorganize stream reject after MUX closure
MINOR: mux-quic: add function for ALPN to app-ops conversion
MEDIUM: quic/mux-quic: adjust app-ops install
MINOR: quic: use server cache for ALPN on BE side
Christopher Faulet (23):
BUG/MEDIUM: spoe: Acquire context buffer in applet before consuming a
frame
BUG/MEDIUM: stream: Handle TASK_WOKEN_RES as a stream event
BUG/MINOR: hlua: Properly enable/disable line receives from HTTP applet
BUG/MEDIUM: hlua: Fix end of request detection when retrieving payload
BUG/MINOR: hlua: Properly enable/disable receives for TCP applets
MINOR: htx: Add a function to retrieve the HTTP version from a start-line
MINOR: h1-htx: Reports non-HTTP version via dedicated flags
BUG/MINOR: h1-htx: Be sure that H1 response version starts by "HTTP/"
MINOR: http-ana: Save the message version in the http_msg structure
MEDIUM: http-fetch: Rework how HTTP message version is retrieved
MEDIUM: http-ana: Use the version of the opposite side for internal
messages
DEBUG: stream: Display the currently running rule in stream dump
MINOR: filters: Use filter API as far as poissible to break loops on
filters
MINOR: filters: Set last_entity when a filter fails on stream_start
callback
MINOR: stream: Display the currently running filter per channel in stream
dump
DOC: config: Use the right alias for %B
BUG/MINOR: channel: Increase the stconn bytes_in value in
channel_add_input()
BUG/MINOR: sample: Fix sample to retrieve the number of bytes received
and sent
BUG/MINOR: http-ana: Increment scf bytes_out value if an haproxy error is
sent
BUG/MAJOR: fcgi: Fix param decoding by properly checking its size
BUG/MAJOR: resolvers: Properly lowered the names found in DNS response
BUG/MEDIUM: mux-fcgi: Use a safe loop to resume each stream eligible for
sending
MINOR: mux-fcgi: Use a dedicated function to resume streams eligible for
sending
Frederic Lecaille (14):
MINOR: haterm: provide -b and -c options (RSA key size, ECDSA curves)
MINOR: haterm: add long options for QUIC and TCP "bind" settings
BUG/MINOR: haterm: missing allocation check in copy_argv()
CLEANUP: haterm: remove unreachable labels hstream_add_data()
CLEANUP: haterm: avoid static analyzer warnings about rand() use
CLEANUP: ssl: Remove a useless variable from ssl_gen_x509()
BUG/MINOR: haterm: cannot reset default "haterm" mode
BUG/MINOR: quic: missing app ops init during backend 0-RTT sessions
CLEANUP: ssl: remove outdated comments
BUG/MAJOR: qpack: unchecked length passed to huffman decoder
BUG/MINOR: qpack: fix 1-byte OOB read in qpack_decode_fs_pfx()
BUG/MINOR: quic: fix OOB read in preferred_address transport parameter
BUG/MEDIUM: qpack: correctly deal with too large decoded numbers
CLEANUP: qpack: simplify length checks in qpack_decode_fs()
Hyeonggeun Oh (1):
MINOR: ssl: clarify error reporting for unsupported keywords
Ilia Shipitsin (2):
CI: use the latest docker for QUIC Interop
CI: remove redundant "halog" compilation
Maxime Henrion (1):
MINOR: quic: add a new metric for ncbuf failures
Mia Kanashi (1):
BUG/MINOR: acme: fix incorrect number of arguments allowed in config
Olivier Houchard (5):
BUG/MEDIUM: cpu-topo: Distribute CPUs fairly across groups
MINOR: counters: Introduce COUNTERS_UPDATE_MAX()
MINOR: listeners: Update the frequency counters separately when needed
MINOR: proxies: Update beconn separately
MINOR: stats: Add an option to disable the calculation of max counters
William Lallemand (3):
CLEANUP: acme: remove duplicate includes
BUG/MINOR: acme: acme_ctx_destroy() leaks auth->dns
BUG/MINOR: acme: wrong labels logic always memprintf errmsg
Willy Tarreau (20):
CLENAUP: cfgparse: accept-invalid-http-* does not support "no"/"defaults"
MINOR: traces: always mark trace_source as thread-aligned
MINOR: mux-h2: also count glitches on invalid trailers
MINOR: mux-h2: add a new setting, "tune.h2.log-errors" to tweak error
logging
BUG/MEDIUM: mux-h2: make sure to always report pending errors to the
stream
BUG/MINOR: server: adjust initialization order for dynamic servers
CLEANUP: tree-wide: drop a few useless null-checks before free()
CLEANUP: quic-stats: include counters from quic_stats
REORG: stats/counters: move extra_counters to counters not stats
CLEANUP: stats: drop stats.h / stats-t.h where not needed
MEDIUM: counters: change the fill_stats() API to pass the module and
extra_counters
CLEANUP: counters: only retrieve zeroes for unallocated extra_counters
MEDIUM: counters: add a dedicated storage for extra_counters in various
structs
MINOR: counters: store a tgroup step for extra_counters to access
multiple tgroups
MEDIUM: counters: store the number of thread groups accessing
extra_counters
MINOR: counters: add EXTRA_COUNTERS_BASE() to retrieve extra_counters
base storage
MEDIUM: counters: return aggregate extra counters in ->fill_stats()
MEDIUM: counters: make EXTRA_COUNTERS_GET() consider tgid
BUG/MINOR: call EXTRA_COUNTERS_FREE() before srv_free_params() in
srv_drop()
BUG/MEDIUM: hpack: correctly deal with too large decoded numbers
---