惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
V
Visual Studio Blog
博客园 - Franky
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
小众软件
小众软件
Jina AI
Jina AI
L
Lohrmann on Cybersecurity
罗磊的独立博客
I
Intezer
W
WeLiveSecurity
T
Tenable Blog
Cyberwarzone
Cyberwarzone
P
Privacy & Cybersecurity Law Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Securelist
Recent Announcements
Recent Announcements
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Engineering at Meta
Engineering at Meta
Hacker News: Ask HN
Hacker News: Ask HN
F
Full Disclosure
S
SegmentFault 最新的问题
S
Security Affairs
L
LINUX DO - 热门话题
C
CERT Recently Published Vulnerability Notes
博客园 - 叶小钗
Stack Overflow Blog
Stack Overflow Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Secure Thoughts
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Register - Security
The Register - Security
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
Last Week in AI
Last Week in AI
PCI Perspectives
PCI Perspectives
N
News | PayPal Newsroom
Schneier on Security
Schneier on Security
T
Threat Research - Cisco Blogs
B
Blog RSS Feed
L
LINUX DO - 最新话题
F
Fortinet All Blogs
雷峰网
雷峰网
Security Latest
Security Latest
大猫的无限游戏
大猫的无限游戏
P
Palo Alto Networks Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
人人都是产品经理
人人都是产品经理
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 【当耐特】

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Inside Streamlit's Re-Run Model — Why Hot Reload Feels Instant
soy · 2026-05-19 · via DEV Community

The first time you save a Streamlit file in your editor and watch the browser update before your hand leaves the keyboard, you assume it is some clever diffing magic. It is not. The mechanism underneath is closer to a confession than an algorithm: Streamlit just re-runs your entire Python script, top to bottom, every time anything changes.

Once you understand that, the whole framework stops feeling magical and starts feeling honest. This post is about why that decision was the right one, what makes it fast, and the small handful of concepts you actually need to internalize to use it well.

If you want the strategic context for why this matters — Snowflake's acquisition, Cortex Search, the Community Cloud economics — that's in the companion piece Why Snowflake's Bet on Streamlit Just Works. This article is the engineering deep-dive.

What "hot reload" usually costs

In a normal Python web stack — FastAPI plus uvicorn, Flask plus gunicorn, Django plus anything — the server process is long-running. It holds the routes, the app state, the database connection pool, the imported modules. When you change a file, the dev server has to:

  1. Detect the file change.
  2. Tear down the existing process (or at least invalidate its module cache).
  3. Re-import everything from scratch.
  4. Rebind routes and middleware.
  5. Open new sockets and resume accepting connections.

The fastest dev servers in this style — uvicorn with --reload, Flask's debugger, Django's runserver — manage this in a few seconds on a small app and noticeably longer on a real one. You save a file, you tab over to the browser, you refresh, you wait. The loop is one or two seconds, which sounds fine on paper but turns "tweak the padding" into a five-minute task.

The cost is structural. As long as there is a server process to restart, restart time has a floor.

What Streamlit does instead

Streamlit's mental model removes the server-process-as-stateful-thing entirely. The server is still there — it accepts HTTP, it serves WebSocket frames — but your app code is not living inside it across requests. Your script is a script. It runs from the first line to the last line, draws the UI as a side effect, and exits.

When something changes — you saved the file, the user clicked a button, a slider moved — the runner just runs your script again. From scratch. Top to bottom. As if you had typed python app.py at a terminal.

import streamlit as st

st.title("A small demo")
n = st.slider("Pick a number", 1, 100, 50)
st.write(f"You picked {n}.")

Enter fullscreen mode Exit fullscreen mode

When the slider moves, the entire file executes again. st.title runs again. st.slider runs again (and returns the new value). st.write runs again. The browser sees the new state.

The reason this is fast is that there is no restart cost. A Python script of a few hundred lines takes single-digit milliseconds to execute if you've avoided heavy work at module scope. The runner is just calling your function in a loop and shipping the resulting UI tree over a socket.

The WebSocket pipe

The other half of the trick is on the wire. A traditional web app communicates with the browser through HTTP request/response cycles — the browser asks for a page, the server returns one, repeat. Hot reload in that world means the browser has to either poll or re-request.

Streamlit holds a persistent WebSocket connection between the browser tab and the server for the entire session. The server runs your script, builds the UI tree, diffs it against what the browser is currently showing, and pushes only the changed nodes through the socket. No page refresh, no F5, no re-fetch.

This is what closes the loop between "I saved a file" and "the screen updated." A file system watcher inside the Streamlit dev server picks up the change, triggers a re-run of your script, the new UI tree gets diffed against the last one, and the delta lands in the browser through the open socket — all within the time it takes you to glance at the browser window.

In production on Streamlit Community Cloud or Streamlit in Snowflake, the file watcher is gone (the code isn't changing), but the rest of the machinery is identical. Every user interaction triggers a script re-run, and the WebSocket pushes the diff back.

The three concepts you actually have to learn

The re-run model has one obvious problem. If your script runs from scratch every time, how do you keep anything across reruns? How do you avoid re-loading a 4 GB model on every click?

Streamlit's answer is three explicit escape hatches. That is the entire API surface for state and persistence. Learn these three, and you can build almost anything.

1. st.session_state for per-session memory

A dictionary scoped to the current browser session. Survives reruns. Does not survive the user closing the tab or the app sleeping.

import streamlit as st

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

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

st.write(f"Clicked {st.session_state.count} times.")

Enter fullscreen mode Exit fullscreen mode

Without session_state, that counter would reset to zero on every click, because the script re-runs from scratch and count = 0 would execute again.

2. @st.cache_data for expensive data

Decorator for pure-ish functions that return data. Streamlit hashes the arguments, executes the function once, and returns the cached result on subsequent calls with the same inputs. Cache survives reruns and (optionally) reboots.

import streamlit as st
import pandas as pd

@st.cache_data(ttl=3600)  # cache for an hour
def load_sales():
    return pd.read_parquet("sales.parquet")

df = load_sales()
st.dataframe(df)

Enter fullscreen mode Exit fullscreen mode

Without the decorator, that Parquet file would be read from disk on every script re-run — every slider move, every button click.

3. @st.cache_resource for expensive objects

Same idea as cache_data, but for things you do not want serialized — database connections, ML models, anything where the object identity matters or where pickling would be wasteful.

import streamlit as st
from sentence_transformers import SentenceTransformer

@st.cache_resource
def get_model():
    return SentenceTransformer("intfloat/multilingual-e5-base")

model = get_model()

Enter fullscreen mode Exit fullscreen mode

Without this, your 400 MB embedding model would be re-loaded into VRAM on every interaction. With it, the model lives for the lifetime of the server process and is shared across all sessions.

That is the entire mental model. session_state for "remember this for this user." cache_data for "remember this value." cache_resource for "remember this object." Compared to learning the React component lifecycle or FastAPI's dependency injection system, this is genuinely a few hours of reading.

Where the re-run model gets in your way

It is not free, and pretending otherwise would be dishonest.

Side effects at module scope are dangerous. If you write requests.get(...) at the top level of your script, that HTTP call fires on every re-run. Wrap anything I/O in @st.cache_data or a function called conditionally.

Long-running operations block the UI. A re-run is synchronous from the user's point of view. If a click triggers a function that takes ten seconds, the UI freezes for ten seconds. Stream output, show progress with st.status, or push the work to a background process.

Mutable globals do not behave the way you expect. If you mutate a module-level list inside your script, that mutation will or will not be visible on the next re-run depending on whether Python's module cache is reused. Use session_state for anything that needs to mutate.

Forms exist for a reason. Without st.form, every widget interaction triggers an immediate re-run. For multi-field inputs where you want one submission, wrap them in a form so the re-run fires only on submit.

None of these are deal-breakers, but they are real, and they reward writing your Streamlit code more like a pure function than like a stateful class.

Why the design holds up

The re-run model is the architectural decision that most defines Streamlit. It is also the one most likely to make a senior backend engineer wince on first contact. "You re-run the whole script every time? That's absurd."

It works because two things are true simultaneously. Python is fast enough at executing a few hundred lines that re-running in milliseconds is achievable. And the three escape hatches — session, data cache, resource cache — give you the exit valves you actually need without inventing a state-management framework.

The result is that the simple case is genuinely simple — five lines of Python and you have a working app — and the complex case is still tractable, you just have to be honest about where your state lives.

For a UI library aimed at data and ML practitioners who do not want to learn web frameworks, this is the right trade. The fact that it also produces the fastest "save file, see change" loop in Python is a free side effect of the architecture, and it is the thing that keeps the framework feeling lightweight even as the apps you build on it grow.


If you want to see this architecture stitched together with Snowflake's strategic bet and Community Cloud's deployment story, the hub article is Why Snowflake's Bet on Streamlit Just Works — And Where Solo Builders Still Win.