Welcome to Module 3!

At this point, your Streamlit app is taking solid shape—but what happens when you connect heavy data that takes 10 seconds to load and your app reloads every time a user clicks?

In this module, we’ll turn your script from a simple prototype into a robust production application. We’ll learn to cache data in memory, keep variables alive between clicks, and structure screens worthy of a designer.


Extreme Performance with @st.cache_data

Streamlit’s rule says: everything re-runs. If you have a function that reads a 500MB CSV from a server, Streamlit will download that CSV every time someone touches a button!

The solution is @st.cache_data. This decorator memoizes the function’s result. If the function’s arguments don’t change, Streamlit returns the cache instantly, without re-running the code inside it.

import streamlit as st
import pandas as pd
import time

@st.cache_data
def load_heavy_data(path):
 # This will take 5 seconds only the first time.
 time.sleep(5)
 return pd.read_csv(path)

with st.spinner("Loading database..."):
 # First time: wait 5s
 # Second time: instant!
 df = load_heavy_data("data.csv")

The brain of the application: st.session_state

As we saw in Module 1, variables reset to their initial values on every interaction. How do we store information between reloads (like the current user, a shopping cart, or a click counter)?

We use st.session_state, which is like a Python dictionary but persistent for each user.

# Initialize the variable if it doesn't exist
if "counter" not in st.session_state:
 st.session_state.counter = 0

# Modify it on click
if st.button("Add +1"):
 st.session_state.counter += 1

st.metric("Total clicks", st.session_state.counter)

Golden rule: Always initialize your variables in session_state at the start of the script before trying to read them.


Advanced Layout: Screens that impress

Nobody wants an app where everything is one endless column. Use these tools to design your interface:

1. Columns (st.columns)

Split the space horizontally to place your KPIs or charts side by side.

col1, col2, col3 = st.columns([1, 1, 2]) # The last column is twice as wide

with col1:
 st.metric("Sales", "$45,200", "+12%")
with col2:
 st.metric("Customers", "1,234", "+8%")
with col3:
 st.write("Wider column for descriptive text.")

2. Tabs (st.tabs)

Avoid infinite scroll by organizing your views into Tabs.

tab_data, tab_charts = st.tabs([" Raw Data", " Analysis"])

with tab_data:
 st.dataframe(df)

with tab_charts:
 st.line_chart(df)

3. Expanders and Popovers

  • st.expander: Hide text sections that aren’t urgent, such as logs, methodologies, or advanced settings.
  • st.popover: A floating panel similar to a tooltip but interactive. Perfect for housing multiple filters without filling your entire sidebar!
with st.popover(" Visual Settings"):
 color = st.color_picker("Pick a color", "#FF0000")
 opacity = st.slider("Opacity", 0, 100)

Special Components and Enhanced Tables

In recent versions, Streamlit has integrated many UI improvements:

  • Modals (@st.dialog): You can open windows that block the application—ideal for delete confirmations ("Are you sure you want to delete this record?").
  • st.logo: Place your company logo statically in the top-left corner of the sidebar menu.
  • st.column_config: Tired of flat tables? With column_config, turn DataFrame columns into visual progress bars (ProgressColumn), rendered images (ImageColumn), or hyperlinks (LinkColumn).
st.dataframe(
 df,
 column_config={
 "sales": st.column_config.ProgressColumn(
 "Sales Goals", min_value=0, max_value=100
 )
 }
)

By understanding cache memory, session state, and the columns/tabs system, your Streamlit skills will have leveled up to Senior. Let’s optimize your applications and take them to production in Module 4!