How to configure an idle timeout for a Streamlit app deployed on GCP Cloud Run?

Context:

I have built a Streamlit app and deployed it in a Docker container on GCP Cloud Run. However, I’m facing an issue: the app never goes idle, even when it’s running in an unused Chrome tab. As a result, GCP bills me approximately $30/day, which is not sustainable.

Problem:

I configured timeoutSeconds=600 (10 minutes) in the Cloud Run yaml file, expecting the container to shut down after 10 minutes of inactivity. However, the app does not respect this limit. Instead, I observe the following logs repeatedly:

GET 304    3 ms Chrome 131 run.app/_stcore/host-config  
GET 304    3 ms Chrome 131 run.app/_stcore/health  
GET 101  601  s Chrome 131 run.app/_stcore/stream  

It seems Streamlit is waking up the container before it can fully shut down, creating an infinite loop where the service never truly goes idle.

Attempts to resolve the issue:

  1. Adjusting Cloud Run timeout:

I suspected the 10-minute timeout of Cloud Run was interfering with Streamlit’s behavior. I read that Streamlit apps deployed in some contexts (e.g., Streamlit on Snowflake) have a default idle timeout of 15 minutes. To test this, I increased the Cloud Run timeout to 20 minutes. Unfortunately, this did not resolve the problem, and the logs remained the same.

  1. Exploring Streamlit’s configuration:

• I checked the config.toml documentation but found no parameter related to idle timeout.

• I also attempted to use code snippets like this to trigger idle behavior, but without success:

st.components.v1.html(
    """
    <script>
    let lastActivity = Date.now();
    const INACTIVITY_DELAY = 5000; // 5 seconds
    setInterval(() => {
      if (Date.now() - lastActivity > INACTIVITY_DELAY) {
        window.location.href = "about:blank";
      }
    }, 1000);
    document.onmousemove = () => lastActivity = Date.now();
    document.onkeypress = () => lastActivity = Date.now();
    </script>
    """,
    height=0,
)

This code (by ChatGPT) is designed to detect user inactivity in the browser and redirect to about:blank after a specified timeout (e.g., 5 seconds). However, despite the inactivity threshold being reached, the redirection does not occur as expected.

  1. Investigating Streamlit’s codebase:

I explored Streamlit’s internal codebase and came across components like websocket_session_manager.py (WebSocketSessionManager) and browser_websocket_handler.py (BrowserWebSocketHandler). However, I’m unsure how to leverage these low-level components effectively, and modifying them doesn’t seem like a stable or sustainable solution.

  1. Searching for solutions on the Streamlit forum:

I found many similar questions in the forum, but most were closed without clear answers. For example:

Does Streamlit have a maximum run time for functions?

How to increase websocket timeout?

Setting custom timeout time

These threads suggest timeouts between 10-20 minutes for Streamlit apps, but the information is inconsistent and often specific to Streamlit Cloud rather than open-source deployments.

Question:

Is there an official or recommended way to configure an idle timeout for an open-source Streamlit app deployed on GCP Cloud Run? Specifically:

• How can I ensure the app goes fully idle and stops consuming resources when it is not actively used?

• Are there any best practices for handling WebSocket connections in this context?

Thank you for your help!

I would greatly appreciate any guidance or examples from others who have solved similar issues.

1 Like

I’m facing the same problem. I am interested in getting the solution.