We have considered this issue before, but have not yet identified a satisfying solution.
The heartbeat mechanism that is currently in place to deal with this, works well enough, but has some drawbacks as you observed.
Note that the container doesn’t stop before the timeout expires: both the container and the HTTP port are released at the same time, after timeout expiration.
The main problem is that Shinyproxy (or any other HTTP server) has no reliable way of seeing that the interaction has ended, aside from a timeout approach.
The only recommendation I can make, is to try decreasing the heartbeat-timeout value.