Over the last few months a lot of work has gone into the PAGI specification and its reference server PAGI::Server to make it more resilient under more real life workloads. The main focus of this release is to make PAGI::Server dependable when clients misbehave or connections end at awkward moments. Clients can abandon uploads, stop reading responses, send malformed traffic, or disappear halfway through a WebSocket closing handshake. Across HTTP, WebSocket, and SSE, the server should handle those cases predictably: report what actually happened, distinguish successful completion from an interrupted exchange, settle pending operations, and release resources without losing cleanup notifications. Much of the work tightens the boundaries between application code, protocol handling, and transport shutdown so a broken request or connection stays contained instead of crashing a worker, leaving work hanging, or disrupting unrelated clients.
The main downside is a more complicated connection lifecycle, with additional bookkeeping and scheduling costs. Distinguishing successful completion from a dropped connection, settling pending operations, and delivering cleanup notifications safely all require work.
All this new code has a price. We initially saw a substantial throughput penalty, and recovered much of it through simplification and targeted optimizations. The latest Linux hello-world comparison puts current roughly level with release, so I would not describe the final result as universally slower, although on some platforms and loops naive testing can be as big as a 10% penalty. However there's nuances worth reviewing. Here's the current CPAN 'hello world' application running single process on my ancient MacBook:
jnapiorkowski@MM-MAC-11294 PAGI-Server % hey -z 30s -c 500 http://127.0.0.1:5000
Summary:
Total: 30.0754 secs
Slowest: 7.7348 secs
Fastest: 0.0247 secs
Average: 0.1365 secs
Requests/sec: 3660.0307
Response time histogram:
0.025 [1] |
0.796 [109681] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
1.567 [45] |
2.338 [43] |
3.109 [44] |
3.880 [42] |
4.651 [43] |
5.422 [44] |
6.193 [45] |
6.964 [43] |
7.735 [46] |
Latency distribution:
10% in 0.0976 secs
25% in 0.1069 secs
50% in 0.1293 secs
75% in 0.1350 secs
90% in 0.1381 secs
95% in 0.1406 secs
99% in 0.1443 secs
Status code distribution:
[200] 110077 responses
Again, these numbers are going to be for relative comparison, not an indication of the floor or ceiling to PAGI::Server performance. Here now is the proposed release, same toy application, single process:
jnapiorkowski@MM-MAC-11294 PAGI-Server % hey -z 30s -c 500 http://127.0.0.1:5000
Summary:
Total: 30.0849 secs
Slowest: 0.4407 secs
Fastest: 0.0288 secs
Average: 0.1515 secs
Requests/sec: 3294.1495
Response time histogram:
0.029 [1] |
0.070 [15] |
0.111 [356] |
0.152 [68688] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.194 [24604] |■■■■■■■■■■■■■■
0.235 [4187] |■■
0.276 [667] |
0.317 [95] |
0.358 [447] |
0.400 [0] |
0.441 [44] |
Latency distribution:
10% in 0.1335 secs
25% in 0.1396 secs
50% in 0.1470 secs
75% in 0.1552 secs
90% in 0.1710 secs
95% in 0.1954 secs
99% in 0.2430 secs
Status code distribution:
[200] 99104 responses
Right off the top on my Mac the top line requests per second is around 10% slower. But if you look more carefully at the histogram you can see that the proposed release is vastly more consistent. The vast majority of users under the proposed release have a multi order faster experience and there's no tail issues like in current blocking some users for up to 8 seconds.
A lot of that improvement has to do with the work put into the server to do a better job of handling complex concurrency situations. Its also a great example of why I'm always saying just looking at top line requests per second of toy applications tells you basically nothing about how a server is going to run under true, complex production situations.
The main goal of PAGI::Server is to be a usable, reference server for the PAGI Specification. Its goal is to have performance characteristics at least as good as other popular, pure Perl servers such as Starlette, Starman and others. For this goal, I believe PAGI::Server is a success. It is my hope that as the specification continues to mature, other servers with different performance goals will emerge.
There is also a concrete upgrade cost: the clarified refusal and connection contracts break some older integrations. That needs coordinated releases and clear migration guidance. Right now I'm in the process of figuring out what that migration looks like, and working with the various authors who have been early adopters of PAGI to make sure this release upgrades smoothly.
The PAGI specification continues to evolve in response to real world issues. When I release the specification at the beginning of 2026, I set a goal of getting PAGI to a place of maturity before the start of 2027. This last set of work moves the needle on that considerably.
Top comments (0)