Courses/Streamlit: 20 Real Apps/Module 2: Streamlit Fundamentals
Module 2 · Lesson 330 minBeginner

Session State — Giving Your App Memory

Lesson goal
Solve the #1 Streamlit confusion: why variables vanish between clicks, and how session state fixes it.

Session state — giving your app memory

Here's the mistake every Streamlit beginner makes:

code
import streamlit as st

count = 0

if st.button("Add one"):
    count = count + 1

st.write(f"Count: {count}")

Click the button. The count shows 1. Click again... still 1. Forever 1. Why?

Why variables vanish

Remember the rerun model: every click re-runs the whole script from the top. So count = 0 runs *again*, wiping your increment before it ever displays. Plain variables have the memory of a goldfish.

The fix: st.session_state

st.session_state is a dictionary that survives reruns. It's your app's memory:

code
import streamlit as st

if "count" not in st.session_state:
    st.session_state.count = 0

if st.button("Add one"):
    st.session_state.count += 1

st.write(f"Count: {st.session_state.count}")

Click away now — it climbs: 1, 2, 3... The value lives in session state, so reruns no longer erase it.

The pattern to memorize

code
if "my_key" not in st.session_state:
    st.session_state.my_key = initial_value

Initialize before you read. This one pattern prevents the most common Streamlit crash (KeyError) — check the key exists first, set a default if not.

Where you'll use it (real examples from this course)

  • Quiz app — which question number the user is on
  • Countdown timer — the deadline they're counting toward
  • To-do list — the list of tasks between actions
  • Typing test — when the timer started
  • If an app needs to *remember* anything longer than one rerun, it goes in session state.

    Clearing memory (restarts)

    code
    if st.button("Restart"):
        for key in ["count", "history"]:
            st.session_state.pop(key, None)
        st.rerun()

    pop(key, None) removes a key safely (no crash if it's missing) — that's how apps "start over".

    Common Errors & Fixes

  • KeyError: 'count' — you read st.session_state.count before initializing it. Use the initialize-first pattern.
  • Value updates but display lags one click behind — you're displaying before updating. Update the state *first*, then display (or call st.rerun() after changing state).
  • State resets when I restart the app — session state lives per browser session; closing the tab or restarting the server clears it. That's expected.
  • What to try next

    Build a click-counter with a Reset button and a "highest count ever" that survives resets (hint: store two keys, only reset one).

    Checkpoint
    You can build a counter that survives reruns and a list that grows with each button press.
    What you learned
    • Why plain variables reset on every interaction
    • st.session_state as your app's memory
    • The initialize-before-read pattern