DEV Community

John Napiorkowski
John Napiorkowski

Posted on

The Next Release of PAGI::Server Will Be Slower, and that's Fine.

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)