Serverless Instance Freezing and Postgres Pooler Client Slot Exhaustion: A Next.js and Supabase Production Case and Local Reproduction
Jaeho Lim· NextGen AI Co.
The original PDF is written in Korean.
Abstract
Serverless functions have their execution environments frozen after responding. How the connections that an application has opened to a transaction pooler persist at that point is not well understood. This paper reconstructs the connection failures that recurred from July to September 2026 in zenith, an internal tool built with Next.js, Vercel, and Supabase, from 11 incident records and 16 commits, and classifies their causes into four mechanisms. The core failure was the exhaustion of the pooler's 200 client slots, and it recurred even after the pool limit was lowered from 10 to 4. Because idle timers do not run on frozen instances, we formulate a model, W·min(q, m), in which occupancy is proportional to W, the number of instances that have handled at least one request. In a reproduction experiment that emulated freezing with a process stop signal and a slot limit of 40 with a TCP proxy, the peak occupancy of the two configurations relying solely on timers equaled min(W·min(q, m), 40) under all conditions, and 6 instances failed with a limit of 4 at W = 16. A release configuration that closes sockets once the entire pool has become quiet kept peak occupancy at 32–36, below the limit of 40, even when the number of instances was increased from 8 to 16, with no failures. In exchange, the median latency of successful requests increased by 2.6–8.7 ms. When freezing was shorter than the idle timer and the socket was disconnected in the meantime, among the three defensive configurations only replacing the pool before each query made both the first request and the retry succeed.
Key Contributions
- We reconstruct the failure lineage from 11 production records and 16 commits, and classify the causes into four mechanisms (slot occupancy by frozen sockets, dead-socket hangs, release interference between concurrent requests, and loss of pipelined statements).
- We formulate a model of slot occupancy under instance freezing. Under timer-based cleanup, it predicts that occupancy is proportional not to the number of active instances but to the number of instances that have handled at least one request.
- We build a reproduction environment that emulates freezing with a process stop signal (
SIGSTOP). In that environment, we measure the prediction and the differences among three release configurations.
Conclusion
On serverless instances that freeze immediately after responding, timer-based cleanup and pool limits did not bound the occupancy of pooler client slots. In the reproduction experiment, occupancy followed min(W·min(q, m), L), and lowering the limit only delayed the point of exhaustion. Releasing sockets once the entire pool had become quiet kept peak occupancy at 32–36 even when the number of instances was increased from 8 to 16. The cost is connection establishment per request (a p50 increase of 2.6–8.7 ms on loopback) and release waiting time. For dead-socket hangs, replacing the pool before each query rescued both the first request and the retry. Future work is to verify timer behavior during freezing on the actual platform and to measure the cost of release waiting.
Comments 0
Loading comments…