Issue
On the legacy router, an H18: Server Request Interrupted typically indicates that the server (aka. dyno) side of the connection closed the connection after sending back some data but not a full HTTP response. Similarly, an H13: Connection closed without response indicates that the dyno closed the connection immediately, before any data could be transferred.
The behavior in Router 2.0 is slightly different. Because Router 2.0 supports HTTP keepalives between the router and dynos, H18
or H13
may also be encountered when a dyno closes an idle connection in 1 of the 2 following ways:
- Gracefully, sending an
RST
packet back to the router. The error may be encountered because a race condition exists between the router using the connection and the dyno closing the connection. Please see the Keepalives section of our HTTP routing documentation for more details. - Ungracefully, without sending back an
RST
packet. Without theRST
packet, the router does not know the connection has closed until attempting to route the next request on that connection.
In both cases, the connection close can happen outside the handling of a request/response. The H18
or H13
will be reported by the router on the next request received.
A typical reason for the dyno to close a connection outside of request handling is due to a server-side idle timeout. Idle timeouts are common practice when building HTTP servers.
This issue is completely avoided in the legacy router because every new request gets a new connection from the router.
Resolution
Easy Solution: Disable Keepalives
The easiest way to avoid H18
or H13
noise in Router 2.0 logs is to disable HTTP keepalives between the router and the dyno:
heroku labs:enable http-disable-keepalive-to-dyno -a <app name>
Better Solution: Increase Server Idle Connection Timeout
The better solution is to increase the server's idle connection timeout to be greater than the idle connection timeout in the router (90 seconds). This is explained more in the Keepalives section of our HTTP routing documentation. Generally, keepalives improve performance as they save time spent handling connections in both the router and the dyno.
Another Recommendation
If your server does not properly implement graceful connection closes, we suggest that you utilize a server that does. This involves ensuring an RST
packet is sent back to the router before the dyno closes the connection. This will allow Router 2.0 to recognize the connection as closed.
Once receiving the RST
packet, any subsequent use of that connection by Router 2.0 will cause an error, internally handled. That error will prompt Router 2.0 to retry by establishing a new connection, never surfacing the internal error to the user if the re-establishment is successful.