Shipping an app to real users raises questions of configuration, hosting, auth and capacity that the dev server hides.
Configuration lives in .streamlit/config.toml (project) or ~/.streamlit/config.toml, and every option can also be a CLI flag or an environment variable: [server] port = 8080 equals --server.port 8080 and STREAMLIT_SERVER_PORT=8080. streamlit config show lists all options. Common ones: server.port, server.address, server.headless = true (no browser), server.maxUploadSize (MB), server.baseUrlPath behind a proxy, client.toolbarMode, and a [theme] section (primaryColor, base, fonts).
Hosting options:
- Streamlit Community Cloud: connect a GitHub repo, set secrets in the UI.
- Containers: a Docker image running
streamlit run app.py --server.port=8501 --server.address=0.0.0.0, with a health check on/_stcore/health. - Snowflake, cloud platforms and Kubernetes. Recent versions also provide
st.App, an ASGI application you can run with uvicorn or mount inside FastAPI or Starlette.
Authentication: st.login() starts an OpenID Connect flow (Google, Microsoft, Okta, Auth0 ...) configured under [auth] in secrets (redirect URI, cookie secret, client id and secret, metadata URL). Afterwards st.user.is_logged_in and st.user attributes such as email are available, and st.logout() ends the session.
Scaling: each user session holds a WebSocket and its session state in the server process, and runs reruns in threads. A single process serves many light users, but CPU-heavy reruns contend for the GIL. Scale out with several replicas behind a load balancer with sticky sessions (WebSocket affinity), share caches through external stores, and keep heavy computation in cached functions or background services.
Example
# .streamlit/config.toml
[server]
headless = true
port = 8501
maxUploadSize = 50 # MB
enableXsrfProtection = true
[theme]
base = "light"
primaryColor = "#E8383D"
# .streamlit/secrets.toml (excerpt) for st.login() with an OIDC provider
[auth]
redirect_uri = "https://app.example.com/oauth2callback"
cookie_secret = "a-long-random-string"
client_id = "..."
client_secret = "..."
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
# Dockerfile essentials:
# CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0"]
# HEALTHCHECK CMD curl -f http://localhost:8501/_stcore/healthRemember
- Options come from config.toml, CLI flags or STREAMLIT_* environment variables
- Deploy via Community Cloud, containers with
/_stcore/health, orst.Appunder ASGI st.loginadds OIDC auth; scale out with sticky sessions and shared caches
Watch out for
- Load balancing replicas without sticky sessions, which breaks the WebSocket connection to a user's session.