SSE Dead Client Detection Issue Behind Apify Standby Proxy
In my SSE endpoint running under Apify Standby mode, the server is unable to reliably detect when clients disconnect. Even when the client closes the browser or loses network connection, the Apify proxy keeps the connection to the Actor open, so the server never receives a proper “disconnect” signal. As a result, the server continues to treat the connection as active and keeps streaming data to a client that no longer exists. Over time, this leads to accumulated dead connections, unnecessary resource usage, and inaccurate connection metrics.
The core issue appears to be that Apify’s proxy does not propagate the actual client disconnect to the Actor. Therefore:
-
close, error, and timeout events are never triggered on the server side,
- the server continues writing data with no feedback that the real client is gone,
- stale SSE connections remain in memory and cannot be cleaned up correctly.
I currently rely on several heuristic workarounds, such as:
- marking a connection as dead if no successful write occurs within a certain time window,
- monitoring pending writes to detect possible dead streams,
- running periodic checks to validate connection state.
These strategies help mitigate the issue but are not fully reliable, since they rely on indirect signals rather than a definitive disconnect notification from the network layer.
For this reason, I need clarification on the following points:
1. Does Apify Standby mode enforce any specific timeout, keep-alive, or proxy behavior for SSE connections?
2. Is there any officially recommended method to detect dead SSE clients when running behind the Apify proxy?
3. Can additional HTTP headers influence how the proxy handles disconnects or keep-alives?2 Replies
Hi, thank you for the detailed explanation.
Let me clarify one thing, as it wasn’t mentioned explicitly.
I’ve seen a similar issue. The problem is that some MCP clients are not closing a connection properly, which leads to accumulated connections on the server.
The client connections are routed to the Actor container via something that is called the standby controller. The standby controller will only terminate the Actor if there is no other active connection. Since the connection is never closed, the running Actor is never terminated. I spent some time debugging this, and the easiest fix at that time was to handle it in the Actor, since each Actor can have custom logic around session handling.
Steps to fix this:
If you are using the old and deprecated SSE transport, please don't use it and instead switch to the modern HTTP Streamable.
Implement a timeout on your server and close the connection. I assume you are working in Python, because I haven't seen this issue with TypeScript.
You can check this example in the Apify templates: https://apify.com/templates/python-mcp-proxy
Please also see our notes here: https://apify.com/templates/python-mcp-proxy#session-management-challenges
To answer your questions:
Does Apify Standby mode enforce any specific timeout, keep-alive, or proxy behavior for SSE connections?No.
Is there any officially recommended method to detect dead SSE clients when running behind the Apify proxy?You can implement session handling and close the dead connection in the Actor.
Can additional HTTP headers influence how the proxy handles disconnects or keep-alives?I’m not aware of that. Hope this helps! Jiri
Hi, just to clarify the current implementation:
my Actor already maintains a full server-side session model for each SSE client, including timestamps for last successful write, last ping, write backpressure, socket/error listeners and periodic health checks. I also send periodic pings from the server side and run aggressive cleanup rules (e.g. no successful write within X seconds, multiple failed writes, excessive pending writes). A background cleanup loop removes any session matching these conditions and ends the response.
So the Actor already closes stale or unresponsive SSE sessions proactively, as you described. However, even this does not fully serve as a stable and reliable solution.
One important detail about this Actor is that it functions as a continuous data pipeline:
clients are expected to connect once and immediately start receiving realtime data. They are not expected to make repeated HTTP requests or maintain their own reconnect logic.
Because of this design, connection stability is quite important for the user experience.
Another challenge I face is that migration events also break the streaming connections, and for a realtime data pipeline this is difficult to handle purely on the server side, the client must reconnect, but this contradicts the “connect once and stream continuously” model.
Given all of this, I have one remaining question:
Does switching from SSE to HTTP Streamable improve how the proxy/standby controller handles disconnects or long-lived connections, or is the behavior essentially identical, meaning timeout-based cleanup and client reconnection remain the only long-term approach for streaming Actors?