Detailed Description of the Problem
I've got my own fcgi application that I've tested with lighttpd.
It also works with haproxy, however the request_id that is maintained by HAProxy only linearily increases on the connection until the connection is closed and re-opened.
Expected Behavior
HAProxy manages the request_id's and should attempt to hold the request_id's as low as possible and to reuse them.
The FCGI Standart states:
The Web server attempts to keep FastCGI request IDs small. That way the application can keep track of request ID states using a short array rather than a long array or a hash table. An application also has the option of accepting only one request at a time. In this case the application simply checks incoming requestId values against the current request ID.
Source: https://fastcgi-archives.github.io/FastCGI_Specification.html#S3.5
Steps to Reproduce the Behavior
Reproducible; every time.
Do you have any idea what may have caused this?
I'm wondering if it's a bug somewhere or simply not implemented.
Do you have an idea how to solve the issue?
Store a set of closed request_id's and use the lowest one for the next request.
What is your configuration?
global
log /dev/log local0
# user haproxy
# group www-data
fcgi-app php-fpm
log-stderr global
docroot /var/www/my-app
# index index.php
# path-info ^(/.+\.php)(/.*)?$
no option get-values
option keep-conn
option mpxs-conns
option max-reqs 500
backend fcgi-servers
mode http
# filter fcgi-app php-fpm
use-fcgi-app php-fpm
# server s1 192.168.0.10:9000 proto fcgi
# server s2 192.168.0.11:9000 proto fcgi
server s1 /var/run/user/1000/wecremote-fastcgi.sock proto fcgi
frontend www
mode http
# bind :8099
bind *:4433 ssl crt ../../../lighttpd.server.pem ssl-min-ver TLSv1.3
# use_backend fcgi-servers if { path_end .php }
# default_backend static-file-servers
default_backend fcgi-servers
# https://www.haproxy.com/documentation/haproxy-configuration-tutorials/alerts-and-monitoring/traces/
traces
trace fcgi verbosity complete
frontend stats
mode http
bind 127.0.0.1:8404
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
Output of haproxy -vv
HAProxy version 3.2.16-1 2026/04/25 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2030.
Known bugs: http://www.haproxy.org/bugs/bugs-3.2.16.html
Running on: Linux 6.19.13+deb14-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.19.13-1 (2026-04-18) x86_64
Build options :
TARGET = linux-glibc
CC = x86_64-linux-gnu-gcc
CFLAGS = -O2 -g -fwrapv -fvect-cost-model=very-cheap -g -O2 -Werror=implicit-function-declaration -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2
OPTIONS = USE_OPENSSL=1 USE_LUA=1 USE_SLZ=1 USE_OT=1 USE_QUIC=1 USE_PROMEX=1 USE_PCRE2=1 USE_PCRE2_JIT=1
DEBUG =
Feature list : -51DEGREES +ACCEPT4 +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL -ENGINE +EPOLL -EVPORTS +GETADDRINFO -KQUEUE -LIBATOMIC +LIBCRYPT +LINUX_CAP +LINUX_SPLICE +LINUX_TPROXY +LUA +MATH -MEMORY_PROFILING +NETFILTER +NS -OBSOLETE_LINKER +OPENSSL -OPENSSL_AWSLC -OPENSSL_WOLFSSL +OT -PCRE +PCRE2 +PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PROCCTL +PROMEX -PTHREAD_EMULATION +QUIC -QUIC_OPENSSL_COMPAT +RT +SLZ +SSL -STATIC_PCRE -STATIC_PCRE2 +TFO +THREAD +THREAD_DUMP +TPROXY -WURFL -ZLIB +ACME
Default settings :
bufsize = 16384, maxrewrite = 1024, maxpollevents = 200
Built with multi-threading support (MAX_TGROUPS=32, MAX_THREADS=1024, default=16).
Built with SSL library version : OpenSSL 3.6.2 7 Apr 2026
Running on SSL library version : OpenSSL 3.6.2 7 Apr 2026
SSL library supports TLS extensions : yes
SSL library supports SNI : yes
SSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
OpenSSL providers loaded : default
QUIC: connection socket-owner mode support : yes
QUIC: GSO emission support : yes
Built with Lua version : Lua 5.4.8
Built with the Prometheus exporter as a service
Built with network namespace support.
Built with OpenTracing support.
Built with libslz for stateless compression.
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.46 2025-08-27
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with gcc compiler version 15.2.0
Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.
Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
quic : mode=HTTP side=FE mux=QUIC flags=HTX|NO_UPG|FRAMED
h2 : mode=HTTP side=FE|BE mux=H2 flags=HTX|HOL_RISK|NO_UPG
<default> : mode=HTTP side=FE|BE mux=H1 flags=HTX
h1 : mode=HTTP side=FE|BE mux=H1 flags=HTX|NO_UPG
fcgi : mode=HTTP side=BE mux=FCGI flags=HTX|HOL_RISK|NO_UPG
<default> : mode=SPOP side=BE mux=SPOP flags=HOL_RISK|NO_UPG
spop : mode=SPOP side=BE mux=SPOP flags=HOL_RISK|NO_UPG
<default> : mode=TCP side=FE|BE mux=PASS flags=
none : mode=TCP side=FE|BE mux=PASS flags=NO_UPG
Available services : prometheus-exporter
Available filters :
[BWLIM] bwlim-in
[BWLIM] bwlim-out
[CACHE] cache
[COMP] compression
[FCGI] fcgi-app
[ OT] opentracing
[SPOE] spoe
[TRACE] trace
Last Outputs and Backtraces
Additional Information
No response
Detailed Description of the Problem
I've got my own fcgi application that I've tested with lighttpd.
It also works with haproxy, however the request_id that is maintained by HAProxy only linearily increases on the connection until the connection is closed and re-opened.
Expected Behavior
HAProxy manages the request_id's and should attempt to hold the request_id's as low as possible and to reuse them.
The FCGI Standart states:
The Web server attempts to keep FastCGI request IDs small. That way the application can keep track of request ID states using a short array rather than a long array or a hash table. An application also has the option of accepting only one request at a time. In this case the application simply checks incoming requestId values against the current request ID.
Source: https://fastcgi-archives.github.io/FastCGI_Specification.html#S3.5
Steps to Reproduce the Behavior
Reproducible; every time.
Do you have any idea what may have caused this?
I'm wondering if it's a bug somewhere or simply not implemented.
Do you have an idea how to solve the issue?
Store a set of closed request_id's and use the lowest one for the next request.
What is your configuration?
Output of
haproxy -vvLast Outputs and Backtraces
Additional Information
No response