Streamlit Best Practices Advanced

Build fast, maintainable, and secure Streamlit applications. This lesson covers performance optimization, app architecture patterns, security considerations, and tips for production-ready apps.

Performance Optimization

  • Cache aggressively: Use @st.cache_data for all data loading and computation, @st.cache_resource for models and connections
  • Use forms for batch input: Prevent unnecessary re-runs by grouping related inputs in st.form
  • Lazy loading: Load data and models only when needed, not at the top of every script run
  • Limit DataFrame size: Display subsets of large DataFrames; use pagination or filters
  • Use st.fragment: For partial re-runs of specific sections without re-running the whole script
  • Optimize images: Resize images before displaying; use st.image(width=...) to control render size

App Architecture

File Structure
my-app/
  app.py                  # Main entry point
  pages/
    1_Dashboard.py        # Page 1
    2_Analysis.py         # Page 2
    3_Settings.py         # Page 3
  utils/
    data.py               # Data loading functions
    models.py             # ML model functions
    helpers.py            # Utility functions
  .streamlit/
    config.toml           # Streamlit configuration
    secrets.toml          # Local secrets (gitignored)
  requirements.txt
  .gitignore

Configuration

TOML (.streamlit/config.toml)
[theme]
primaryColor = "#FF4B4B"
backgroundColor = "#FFFFFF"
secondaryBackgroundColor = "#F0F2F6"
textColor = "#262730"
font = "sans serif"

[server]
maxUploadSize = 200
enableCORS = false
enableXsrfProtection = true

[browser]
gatherUsageStats = false

Security Best Practices

Practice Implementation
Never hardcode secrets Use st.secrets or environment variables
Validate user input Check types, ranges, and sanitize before processing
Limit file uploads Restrict file types and sizes with type and maxUploadSize
Enable XSRF protection Set enableXsrfProtection = true in config
Use HTTPS Deploy behind a reverse proxy with TLS
Authentication Use st.experimental_user or third-party auth (Streamlit-Authenticator)

Common Patterns

Error Handling

Python
try:
    result = process_data(user_input)
    st.success("Processing complete!")
    st.write(result)
except ValueError as e:
    st.error(f"Invalid input: {e}")
except Exception as e:
    st.error("An unexpected error occurred. Please try again.")
    st.exception(e)  # Show full traceback in dev mode

Loading States

Python
if st.button("Process Data"):
    with st.spinner("Processing..."):
        result = long_running_function()
    st.success("Done!")
    st.balloons()  # Celebrate!

Testing

  • Unit test utilities: Test your data processing and ML functions independently from Streamlit
  • AppTest: Use streamlit.testing.v1.AppTest for automated UI testing
  • Manual testing: Test across browsers and screen sizes
  • Performance profiling: Use st.cache_data.clear() to test cold start performance

Production Checklist

  • All sensitive values stored in secrets, not in code
  • Error handling on all user inputs and API calls
  • Loading indicators for slow operations
  • Responsive layout tested on mobile
  • Requirements pinned to specific versions
  • st.set_page_config() called at the very top
  • Cache decorators on all data loading and model functions
  • Favicon and page title configured
  • .gitignore includes .streamlit/secrets.toml
Key Takeaway: Streamlit apps are scripts that re-run on every interaction. The three pillars of a well-built Streamlit app are: aggressive caching (for speed), session state (for persistence), and forms (for batched input). Master these three, and your apps will feel snappy and professional.

Course Complete!

Congratulations! You have mastered Streamlit from basics to production deployment. You can now build, style, and deploy data-driven Python web applications with confidence.

← Back to Course Overview

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.