What Is New in HAProxy 3.4
| Category | Highlights |
|---|---|
| New Features |
OpenTelemetry filter (addon via EXTRA_MAKE); ACME dns-01 and dns-persist-01 challenges with EAB support;
QMux protocol for QUIC multiplexing; Dynamic backend creation and deletion via CLI;
Large and small buffer pools; haterm HTTP terminal server utility;
filter-sequence directive; JWE decryption converters (jwt_decrypt_secret, jwt_decrypt_cert, jwt_decrypt_jwk);
AES-CBC encrypt/decrypt converters; TCP SYN save option (tcp-ss);
set-headers-bin, add-headers-bin, del-headers-bin HTTP actions;
Healthcheck sections with the healthcheck server keyword;
publish/unpublish backend CLI commands; QUIC backend 0-RTT sessions;
ECDH-ES support in JWT decryption; stats version hidden by default with stats-showversion
|
| Improvements |
Scheduler rework to avoid running the same task multiple times per cycle;
H2 glitch tracking with graceful close at 75% threshold;
H2 adaptive streams limit based on load;
CPU topology enhancements: threads-per-core, cpu-affinity, max-threads-per-group (default raised to 16);
Thread execution context tracking in profiling and dumps;
OpenSSL 4.0 compatibility groundwork; Large buffer support (configurable via tune.bufsize.large);
balance random considers per-thread-group request rate for tie-breaking;
use-small-buffers proxy option; Dynamic extra counters per thread group;
Compression filter split into two distinct filters;
del backend CLI with safe reference counting;
App ops callbacks removed from mux layer (stconn consolidation);
QUIC: MPSC ring buffer, revised RX path, QCS stream traces;
Scheduler budgets tuned to reduce TL_BULK scheduling
|
| Bug Fixes | MAJOR: HTTP authority normalization could corrupt host header with comma or large host values; MAJOR: H3 body size not checked on empty FIN frames; MAJOR: mux-h1 64-bit chunk size emission overflow; MAJOR: SLZ compression worst-case literal output exceeded limits; MAJOR: pattern generation ID was incorrect in pat_ref_append(); MAJOR: QPACK length passed unchecked to Huffman decoder; MAJOR: NTLM private session retrieval; MAJOR: mux-h2 incomplete transfer detection on HEADERS frames; MEDIUM: numerous memory leaks across ACME, SSL, resolvers, maps, patterns, tools; MEDIUM: H2 padding consumption for DATA frames; MEDIUM: dict race condition on refcount increment; MEDIUM: CLI permission checks on stick-table, SSL/OCSP, and map commands; MEDIUM: tasks scheduled while already running; MEDIUM: SPOE context buffer and abort handling |
| Breaking Changes |
OpenTelemetry filter (otel) moved outside HAProxy sources; build now requires EXTRA_MAKE -- USE_OTEL removed;
OpenTracing filter (ot) emits deprecation warnings at build and init time;
max-threads-per-group default changed to 16;
Stats page no longer shows HAProxy version by default -- use stats-showversion to re-enable;
JWE: RSA1_5 algorithm disabled by default in jwt_decrypt converters
|
| Deprecations |
OpenTracing (ot) filter is officially deprecated; it will produce warnings at build time and at filter initialization
|
What major buffer and memory management changes does HAProxy 3.4 introduce?
HAProxy 3.4 introduces a tiered buffer architecture with distinct pools for default, small, and large buffers.
The new tune.bufsize.large global directive lets you configure an oversized buffer pool used for body capture, request buffering during L7 retries, and header fetch operations that require more space than the default buffer permits.
A matching small-buffer pool is used opportunistically when queueing HTTP or TCP streams, reducing memory pressure on high-connection-count frontends.
In practice, the kernel-side zero-copy (fast-forward) path is now disabled whenever source and destination buffers differ in size, which prevents subtle data corruption when buffers are swapped mid-stream.
The use-small-buffers proxy option lets you control per-proxy where small buffers are attempted (frontend receives, health checks, L7 retries).
Watch out for the hard limit: tune.bufsize.large values at or above 256 MB are rejected when HTTP mode is active.
HTX defragmentation was refactored to merge adjacent DATA blocks during transfers, reducing fragmentation overhead on proxied responses.
The htx_xfer() function replaces the older htx_xfer_blks() across the tree and correctly accounts for block-size deltas during partial transfers.
How does HAProxy 3.4 improve QUIC and HTTP/3 support?
HAProxy 3.4 introduces QMux -- a new QUIC multiplexing protocol layer that sits between the QUIC transport and the application protocol. QMux is activated automatically on both frontend and backend sides and provides a dedicated connection transport layer record format over QUIC streams, enabling efficient multiplexing independent of the application-level framing.
Backend QUIC connections now support 0-RTT session resumption. When a prior session's transport parameters have been cached, HAProxy can send early data in the first flight, reducing connection setup latency to QUIC backends. Stored tokens received via NEW_TOKEN frames are saved and reused on subsequent connections to the same server.
Several notable correctness fixes landed for HTTP/3:
- Body size was not validated against Content-Length on empty FIN frames -- a MAJOR bug now fixed.
- Unaligned frames other than DATA are now correctly rejected.
- QPACK huffman decoding received an unchecked length value -- patched to prevent heap overflows.
- GOAWAY reception now correctly prevents new streams on both H3 and the QUIC MUX level.
- A new
fe.stream.max-totalsetting enforces a lifetime stream limit per QUIC connection.
A new quic cc-algo server keyword allows per-server congestion control algorithm selection on the backend side, giving you finer control over QUIC performance profiles when connecting to heterogeneous server pools.
What new observability and diagnostics tools does HAProxy 3.4 provide?
HAProxy 3.4 ships a fully integrated OpenTelemetry filter as an external addon (built via EXTRA_MAKE=otel).
The filter supports trace context propagation via HTTP headers and HAProxy variables, span and link management, metrics instruments, and log-record emission.
CLI commands are included for runtime filter management without a reload.
Thread execution context tracking is a significant internal improvement that surfaces in show profiling and panic thread dumps.
Every task call, applet invocation, MUX operation, sample fetch, and filter callback now records a lightweight caller context.
The show profiling output can now be sorted by calling context in addition to the existing per-pool view, making it much easier to attribute allocation pressure to a specific configuration path.
The set-dumpable=libs mode now reads all loaded shared libraries into memory at startup and optionally copies debug symbols from /usr/lib/debug, making post-mortem core analysis significantly more complete.
A new libs-from-core GDB utility in dev/gdb/ can extract library images from an existing core file for offline analysis.
The show fd CLI command now accepts a thread group ID (<tgid>/<fd>), making it possible to inspect per-group file descriptors on multi-group deployments.
The show info output now includes the number of active thread groups.
What ACME and SSL improvements are included in HAProxy 3.4?
HAProxy 3.4 significantly extends the built-in ACME client.
Two new challenge types are now supported: dns-01 (with a configurable propagation pre-check via the built-in resolver, including a dns-delay and dns-timeout) and dns-persist-01 (a persistent DNS TXT record challenge for environments where the record survives across challenge cycles).
External Account Binding (EAB) is implemented for ACME providers that require pre-registration, with configurable MAC algorithm selection.
Certificate issuance via the crt-store load directive now supports generating certificates directly from configuration, reducing bootstrap complexity for internally issued certs.
The ACME client also now implements draft-ietf-acme-profiles and supports IP SANs in certificate signing requests.
On the SSL library front, HAProxy 3.4 adds groundwork for OpenSSL 4.0 compatibility: X509_STORE_get1_objects() replaces the deprecated iteration API, and ASN1 string accessors replace direct struct member access.
A new ssl_fc_crtname sample fetch exposes the name of the matched certificate store entry.
TLS keylog format variables and environment variable support are added for session key export.
A new aes_cbc_enc and aes_cbc_dec converter pair extends the existing AES-GCM converters.
The jwe subsystem gains jwt_decrypt_secret, jwt_decrypt_cert, and jwt_decrypt_jwk converters, plus ECDH-ES and ECDH-ES+AxxxKW key agreement support.
The RSA1_5 algorithm is disabled by default in jwt_decrypt due to its known vulnerability to padding oracle attacks.
What scheduler and CPU topology changes should operators know about in HAProxy 3.4?
The HAProxy 3.4 scheduler received targeted reworks to reduce spurious task re-queuing.
The key change is that a task is no longer eligible to run again in the same scheduler pass once it has started, eliminating pathological cases where a misbehaving tasklet could monopolize a thread.
Self-waking tasklets no longer incur the previous "punishment" delay when woken by the TASK_WOKEN_ANY flag, improving responsiveness for I/O-driven workloads.
H2 stream processing now operates under a per-connection frames budget to prevent a single high-stream-count connection from starving other work.
CPU topology configuration is significantly more expressive in 3.4.
The new threads-per-core keyword in cpu-policy controls how many hardware threads per physical core HAProxy will use, letting you reserve SMT siblings for other workloads.
The new cpu-affinity per-thread and cpu-affinity per-ccx modes allow binding threads to individual CPUs or CCX (Core Complex) groups respectively, which is valuable on AMD EPYC processors with NUMA-aware topologies.
The max-threads-per-group default has been raised from 8 to 16, which means existing configs that relied on implicit group splitting behavior may now observe fewer thread groups.
Review your nbthread and cpu-map directives before upgrading if you depend on specific group affinity.
Frequently Asked Questions -- HAProxy 3.4
Does the OpenTelemetry filter in HAProxy 3.4 require a separate build?
Yes, the OpenTelemetry filter is built as an external addon using the EXTRA_MAKE mechanism; add EXTRA_MAKE=otel to your build command and the USE_OTEL flag is no longer needed since it has been removed.
Is HAProxy 3.4 compatible with OpenSSL 4.0?
HAProxy 3.4 includes compatibility groundwork for OpenSSL 4.0 by replacing deprecated struct member access with accessor functions, but full support is incremental and you should verify your SSL build against the OpenSSL version in use before deploying.
What happens if I do not set max-threads-per-group after upgrading to 3.4?
The default value changed from 8 to 16 in 3.4, which means HAProxy may create fewer thread groups than before on systems with many threads; if your cpu-map or numa-affinity configuration assumes a specific number of groups you must audit those settings before upgrading.
How does HAProxy 3.4 protect against the RSA1_5 padding oracle vulnerability in JWE decryption?
The RSA1_5 key agreement algorithm is now disabled by default in jwt_decrypt converters; to re-enable it you must explicitly include it via the jwt_decrypt_alg_list option, which allows operators to audit all environments that previously accepted RSA1_5 tokens silently.
Can HAProxy 3.4 create and delete backends at runtime without a reload?
Yes, the new add backend and del backend CLI commands allow dynamic backend lifecycle management at runtime, with reference-count-based safety guards that prevent deletion while active sessions, servers, or configuration elements still reference the backend.
What is the stats-showversion directive introduced in HAProxy 3.4?
Starting in 3.4 the HAProxy version string is hidden from the stats page by default to reduce information disclosure to unauthenticated users; adding stats-showversion to your frontend or defaults section restores the previous behavior.