PAGI 0.001017 is on CPAN. The headline feature is HTTP/2 support in PAGI::Server, built on the nghttp2 C library and validated against h2spec's conformance suite. HTTP/2 is marked experimental in this release -- the protocol works, the compliance numbers are solid, and we want production feedback before dropping that label.
This post focuses on why h2c (cleartext HTTP/2) between your reverse proxy and backend matters, and how PAGI::Server implements it.
The Quick Version
# Install the HTTP/2 dependency
cpanm Net::HTTP2::nghttp2
# Run with HTTP/2 over TLS
pagi-server --http2 --ssl-cert cert.pem --ssl-key key.pem app.pl
# Run with cleartext HTTP/2 (h2c) -- behind a proxy
pagi-server --http2 app.pl
Your app code doesn't change. HTTP/2 is a transport concern handled entirely by the server. The same async handlers that serve HTTP/1.1 serve HTTP/2 without modification.
"I Have nginx in Front, Why Do I Care?"
If nginx terminates TLS and speaks HTTP/2 to clients, why does the backend need HTTP/2 too?
The answer is h2c -- cleartext HTTP/2 between your proxy and your application server. No TLS overhead, but all of HTTP/2's protocol benefits on the internal hop: stream multiplexing over a single TCP connection, HPACK header compression (especially effective for repetitive internal headers like auth tokens and tracing IDs), and per-stream flow control so a slow response on one stream doesn't block others.
The practical wins: fewer TCP connections between proxy and backend (one multiplexed h2c connection replaces a pool of HTTP/1.1 connections), less file descriptor and kernel memory pressure, and no TIME_WAIT churn from connection recycling.
Where h2c Matters
gRPC requires HTTP/2 -- it doesn't work over HTTP/1.1 at all. If you're building gRPC services, h2c is mandatory.
API gateway fan-out is where multiplexing shines. When your gateway fans out to 10 backend services per request, h2c means 1-2 connections per backend instead of a pool of 50-100.
Service mesh environments (Envoy/Istio sidecars) default to HTTP/2 between services. A backend that speaks h2c natively means one less protocol translation.
A Note on Proxies
Not all proxies handle h2c equally:
- Envoy has the best h2c upstream support with full multiplexing
-
Caddy makes it trivial:
reverse_proxy h2c://localhost:8080 -
nginx supports h2c via
grpc_passfor gRPC workloads, but its genericproxy_passdoesn't supportproxy_http_version 2.0
For full multiplexing to backends, Envoy or Caddy are better choices than nginx today.
HTTP/2 Over TLS -- No Proxy Required
h2c isn't the only mode. PAGI::Server also does full HTTP/2 over TLS with ALPN negotiation:
pagi-server --http2 --ssl-cert cert.pem --ssl-key key.pem app.pl
This is useful when you don't want the overhead or complexity of a reverse proxy -- internal tools, admin dashboards, development servers, or any app where the traffic doesn't justify a separate proxy layer. Browsers get HTTP/2 directly, with TLS, no nginx required.
What PAGI::Server Does
Dual-Mode Protocol Detection
With TLS, PAGI::Server uses ALPN negotiation during the handshake -- advertising h2 and http/1.1, letting the client choose. The protocol is decided before the first byte of application data.
Without TLS (h2c mode), PAGI::Server inspects the first 24 bytes of each connection for the HTTP/2 client connection preface. If it matches, the connection upgrades to HTTP/2. If not, it falls through to HTTP/1.1. Both protocols coexist on the same port, same worker -- no configuration needed beyond --http2.
Either way, HTTP/1.1 clients are still served normally. The server handles both protocols on the same port.
WebSocket over HTTP/2 (RFC 8441)
Most HTTP/2 implementations skip this. PAGI::Server supports the Extended CONNECT protocol from RFC 8441, which tunnels WebSocket connections over HTTP/2 streams. Multiple WebSocket connections multiplex over a single TCP connection instead of requiring one TCP connection each.
Compliance
Built on nghttp2 (the same C library behind curl, Firefox, and Apache's mod_http2). PAGI::Server passes 137 of 146 h2spec conformance tests (93.8%). The 9 remaining failures are in nghttp2 itself and shared with every server that uses it. Load tested with h2load at 60,000 requests across 50 concurrent connections with no data loss or protocol violations.
Full test-by-test results are published: HTTP/2 Compliance Results.
Multi-Worker and Tunable
HTTP/2 works in multi-worker prefork mode. Each worker independently handles HTTP/2 sessions:
pagi-server --http2 --workers 4 app.pl
Protocol settings are exposed for environments that need fine-tuning:
my $server = PAGI::Server->new(
app => $app,
http2 => 1,
h2_max_concurrent_streams => 50, # default: 100
h2_initial_window_size => 131072, # default: 65535
h2_max_frame_size => 32768, # default: 16384
h2_max_header_list_size => 32768, # default: 65536
);
Most deployments won't need to touch these. The defaults follow the RFC recommendations.
Context in the Perl Ecosystem
Perl has had HTTP/2 libraries on CPAN (Protocol::HTTP2, Net::HTTP2), but application servers haven't integrated them with validated compliance testing. PAGI::Server is the first to publish h2spec results and ship h2c with automatic protocol detection alongside HTTP/1.1. If you're currently running Starman, Twiggy, or Hypnotoad, none of them offer HTTP/2.
What Else Is in 0.001017
The rest of the release is operational improvements:
-
Worker heartbeat monitoring -- parent process detects workers with blocked event loops and replaces them via SIGKILL + respawn. Default 50s timeout. Only triggers on true event loop starvation; async handlers using
awaitare unaffected. -
Custom access log format -- format strings with atoms like
%a(address),%s(status),%D(duration). -
TLS performance fix -- shared SSL context via
SSL_reuse_ctxeliminates per-connection CA bundle parsing. 26x throughput improvement at 8+ concurrent TLS connections. - SSE wire format fix -- now handles CRLF, LF, and bare CR line endings per the SSE specification.
- Multi-worker fixes -- shutdown escalation, parameter pass-through, and various stability improvements.
Getting Started
# Install PAGI
cpanm PAGI
# Install HTTP/2 support (optional)
cpanm Net::HTTP2::nghttp2
# Run your app with HTTP/2
pagi-server --http2 app.pl
Links
- PAGI 0.001017 on CPAN
- HTTP/2 Compliance Results
- PAGI on GitHub
- h2spec -- HTTP/2 conformance testing tool
Top comments (0)