Thursday, September 24, 2026
HomeData ScienceDeploying ML Models with Streamlit – Complete Guide to Building Data Science...

Deploying ML Models with Streamlit – Complete Guide to Building Data Science Apps

Table of Content

Streamlit is the fastest way to turn a machine learning model or data analysis script into a shareable interactive web application — requiring no frontend development experience. A data scientist who would spend weeks building a Flask + React dashboard can build the same interactive app in Streamlit in a few hours. This has made Streamlit the standard tool for ML demos, internal analytics tools, model monitoring dashboards, and rapid prototyping. This guide covers the complete Streamlit development workflow — from a basic app to a production-ready ML deployment with authentication, caching, and model serving.

Streamlit deployment is the final step in the ML workflow that starts with feature engineering (our Feature Engineering guide), model training and evaluation (our Model Evaluation guide), and production deployment considerations (our MLOps Interview Q&A). The visualisations embedded in Streamlit apps use the libraries in our Data Visualization guide. The models deployed via Streamlit are trained using techniques from our Machine Learning Interview Q&A and Gradient Boosting guide.

Streamlit Fundamentals — How It Works

Streamlit’s execution model is simple: every time the user interacts with a widget (slider, button, text input), the entire Python script re-runs from top to bottom, and Streamlit re-renders only the changed elements. This reactive model means you write linear Python scripts rather than callback functions — dramatically lowering the learning curve. The tradeoff: computationally expensive operations (loading data, training models, calling APIs) must be cached to avoid re-running on every interaction.

import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
import joblib

# --- Page configuration (must be first Streamlit call) ---
st.set_page_config(
    page_title='ML Model Dashboard',
    page_icon='chart_with_upwards_trend',
    layout='wide',
    initial_sidebar_state='expanded'
)

# --- Caching: st.cache_data for data, st.cache_resource for models ---
@st.cache_data
def load_data(file_path):
    '''Load and cache dataset — runs only when file_path changes.'''
    df = pd.read_csv(file_path)
    df['date'] = pd.to_datetime(df['date'])
    return df

@st.cache_resource
def load_model(model_path):
    '''Load and cache model object — shared across sessions.'''
    return joblib.load(model_path)

# --- Sidebar: user inputs ---
st.sidebar.title('Model Configuration')
model_type  = st.sidebar.selectbox('Model', ['GBM', 'RandomForest', 'LogisticRegression'])
threshold   = st.sidebar.slider('Decision Threshold', 0.0, 1.0, 0.5, 0.01)
date_range  = st.sidebar.date_input('Date Range', value=(pd.Timestamp('2026-01-01'),
                                                          pd.Timestamp('2026-09-01')))
show_raw    = st.sidebar.checkbox('Show Raw Data', value=False)

# --- Main page ---
st.title('Churn Prediction Dashboard')
st.markdown('Real-time model scoring and performance monitoring.')

col1, col2, col3, col4 = st.columns(4)
col1.metric('Total Customers',  '124,532',  delta='+1,240')
col2.metric('At-Risk Customers', '8,721',   delta='+312',   delta_color='inverse')
col3.metric('Model AUC',         '0.847',   delta='+0.003')
col4.metric('Intervention Rate', '7.0%',    delta='-0.2%',  delta_color='inverse')

Building an End-to-End ML App

the best way to build web apps without code
Photo by Team Nocoloco on Unsplash
# --- File uploader + prediction ---
st.subheader('Batch Scoring')
uploaded = st.file_uploader('Upload customer CSV', type=['csv'])

if uploaded is not None:
    df_input = pd.read_csv(uploaded)
    st.write('Uploaded:', df_input.shape[0], 'rows,', df_input.shape[1], 'columns')

    if st.button('Run Predictions', type='primary'):
        with st.spinner('Scoring...'):
            model  = load_model('churn_model.pkl')
            probs  = model.predict_proba(df_input)[:, 1]
            preds  = (probs >= threshold).astype(int)

        df_out = df_input.copy()
        df_out['churn_prob']   = probs.round(4)
        df_out['churn_pred']   = preds
        df_out['risk_tier']    = pd.cut(probs,
                                         bins=[0, 0.3, 0.6, 1.0],
                                         labels=['Low', 'Medium', 'High'])

        # Metrics
        c1, c2, c3 = st.columns(3)
        c1.metric('Predicted Churners', int(preds.sum()))
        c2.metric('Avg Churn Probability', str(round(probs.mean()*100, 1)) + '%')
        c3.metric('High Risk Customers', int((probs >= 0.6).sum()))

        # Distribution plot
        fig = px.histogram(df_out, x='churn_prob', nbins=40, color='risk_tier',
                           title='Predicted Churn Probability Distribution',
                           color_discrete_map={'Low':'green','Medium':'orange','High':'red'})
        st.plotly_chart(fig, use_container_width=True)

        # Download results
        csv_out = df_out.to_csv(index=False).encode('utf-8')
        st.download_button('Download Results CSV', csv_out,
                           'churn_predictions.csv', 'text/csv')

        if show_raw:
            st.dataframe(df_out, use_container_width=True)

# --- Real-time single prediction form ---
st.subheader('Single Customer Scoring')
with st.form('customer_form'):
    tenure   = st.number_input('Tenure (months)', 0, 120, 24)
    spend    = st.number_input('Monthly Spend (INR)', 0, 50000, 1200)
    n_calls  = st.number_input('Support Calls (last 3 months)', 0, 50, 2)
    plan     = st.selectbox('Plan Type', ['Basic', 'Standard', 'Premium'])
    submitted = st.form_submit_button('Predict Churn Risk')

if submitted:
    plan_enc = {'Basic': 0, 'Standard': 1, 'Premium': 2}[plan]
    row = np.array([[tenure, spend, n_calls, plan_enc]])
    model = load_model('churn_model.pkl')
    prob  = model.predict_proba(row)[0, 1]

    col_a, col_b = st.columns(2)
    col_a.metric('Churn Probability', str(round(prob*100, 1)) + '%')
    risk = 'High' if prob >= 0.6 else ('Medium' if prob >= 0.3 else 'Low')
    color = 'red' if risk == 'High' else ('orange' if risk == 'Medium' else 'green')
    col_b.markdown('Risk Tier: **:' + color + '[' + risk + ']**')

    if prob >= 0.6:
        st.warning('This customer is at high churn risk. Consider a retention offer.')

Performance, Caching and Production Patterns

Session state — persisting data across reruns: Streamlit’s re-run model resets all local variables on each interaction. Use st.session_state to persist data across reruns within a session:

# Persist state across reruns
if 'predictions' not in st.session_state:
    st.session_state.predictions = None
if 'model_loaded' not in st.session_state:
    st.session_state.model_loaded = False

if st.button('Load Model'):
    st.session_state.model_loaded = True
    st.session_state.model = load_model('model.pkl')

if st.session_state.model_loaded:
    st.success('Model ready')

Multi-page apps: Organise large apps into pages — create a pages/ directory with separate .py files. Streamlit automatically adds navigation. Structure: main_app.py (entry point), pages/1_Overview.py, pages/2_Predictions.py, pages/3_Monitoring.py.

Deployment options:

PlatformBest ForCostSetup Effort
Streamlit Community CloudPublic demos, open-source appsFreeMinimal — connect GitHub repo
AWS EC2 + nginxProduction internal tools~$10-50/monthMedium — server setup required
GCP Cloud Run (containerised)Scalable, auto-scalingPay per requestMedium — Docker + Cloud Run
Azure Container InstancesEnterprise, Azure ecosystemPay per useMedium
Hugging Face SpacesML demos, Gradio/Streamlit appsFree tier availableMinimal — connect GitHub

For deploying models at production scale with versioning, monitoring, and CI/CD — beyond what Streamlit handles — our MLOps Interview Q&A covers FastAPI model serving, Docker containerisation, MLflow model registry, and data drift monitoring. For the data pipelines that feed Streamlit dashboards, our Data Engineering Fundamentals guide covers Airflow, dbt, and the modern data stack. The Plotly visualisations embedded in Streamlit apps are covered in depth in our Data Visualization guide.

Leave feedback about this

  • Rating

Durgesh Kekare
Durgesh Kekarehttps://www.dataexpertise.in
Durgesh Kekare is a data science educator and founder of DataExpertise.in. With expertise in Python, machine learning, and analytics, he helps 10,000+ learners break into data careers.

Latest Posts

List of Categories