streamlit/streamlit
Streamlit — A faster way to build and share data apps.
12 hidden assumptions · 7-stage pipeline · 8 components
Like any codebase, this fullstack makes assumptions it never checks — most are routine. The ones worth your attention are below.
Transforms Python scripts into interactive web apps with real-time updates
Data flows from user Python scripts through protobuf serialization to React components. When users run `streamlit run script.py`, the backend executes the script, capturing st.* function calls as ForwardMsg protobuf messages. These messages stream via WebSocket to the React frontend, which renders them as interactive components. When users interact with widgets, the frontend sends widget values back via WebSocket, triggering script re-execution with updated SessionState, creating a reactive feedback loop.
Under the hood, the system uses 3 feedback loops, 3 data pools, 4 control points to manage its runtime behavior.
A 8-component fullstack. 1963 files analyzed. Data flows through 7 distinct pipeline stages.
Hidden Assumptions
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
Application throws error immediately at startup if host page doesn't have the required root element, preventing entire frontend from loading
Type mismatches between component library and main app cause compilation errors or runtime failures when components try to access props
DataFrame rendering fails if ArrowTable implementation doesn't match expected Arrow Table interface, breaking all tabular data display
Show everything (9 more)
Date.now() at frontend initialization represents when Streamlit script execution started for GUEST_READY messaging
If this fails: GUEST_READY timestamp will be incorrect if frontend loads significantly before or after backend script execution starts, breaking performance metrics or timing-dependent features
frontend/app/src/index.tsx:streamlitExecutionStartedAt
NODE_ENV environment variable is set to 'development' or other recognized value during build process
If this fails: Debug logging remains disabled in development builds if NODE_ENV isn't properly set, making development debugging much harder
frontend/app/src/index.tsx:process.env.NODE_ENV
RenderData generic type ArgType defaults to 'any' to maintain backward compatibility with existing components
If this fails: Components lose type safety for their arguments, allowing runtime type errors when components receive unexpected argument shapes from Python backend
frontend/component-lib/src/index.ts:RenderData
ConnectionManager class provides WebSocket connection lifecycle management with expected methods for frontend-backend communication
If this fails: WebSocket connection handling breaks if ConnectionManager interface changes, causing complete loss of real-time communication between frontend and Python backend
frontend/connection/src/index.ts:ConnectionManager
Development environment detection correctly identifies development vs production based on build configuration or environment variables
If this fails: Debug features or development-only endpoints remain active in production if environment detection fails, potentially exposing internal information
frontend/connection/src/index.ts:IS_DEV_ENV
Default endpoint configuration matches the URL structure and paths expected by Streamlit backend server
If this fails: Frontend cannot connect to backend if endpoint paths don't match server routing, causing complete application failure in default configurations
frontend/connection/src/index.ts:DefaultStreamlitEndpoints
URI parsing function can correctly handle all valid Streamlit deployment URL formats including localhost, cloud deployments, and custom domains
If this fails: Connection fails for non-standard deployments if URI parsing doesn't handle edge cases like IPv6 addresses, non-standard ports, or complex proxy setups
frontend/connection/src/index.ts:parseUriIntoBaseParts
Styletron CSS-in-JS engine with 'st-' prefix won't conflict with existing CSS classes in the host page or other libraries
If this fails: CSS conflicts cause visual corruption or broken styling if host page uses classes with 'st-' prefix or other CSS-in-JS libraries interfere
frontend/app/src/index.tsx:Styletron
React StrictMode double-execution behavior is compatible with all Streamlit components and third-party integrations
If this fails: Components with side effects break in development due to StrictMode double-execution, causing inconsistent behavior between dev and production
frontend/app/src/index.tsx:StrictMode
Open the standalone hidden-assumptions report for streamlit →
How Data Flows Through the System
Data flows from user Python scripts through protobuf serialization to React components. When users run `streamlit run script.py`, the backend executes the script, capturing st.* function calls as ForwardMsg protobuf messages. These messages stream via WebSocket to the React frontend, which renders them as interactive components. When users interact with widgets, the frontend sends widget values back via WebSocket, triggering script re-execution with updated SessionState, creating a reactive feedback loop.
- Parse user script — The ScriptRunner loads the Python file specified in `streamlit run`, compiles it to bytecode, and prepares execution context with Streamlit API imports
- Execute script with state — Python script runs from top to bottom with current SessionState injected as widget default values, each st.* function call generates Element protobuf messages [SessionState → Element]
- Queue UI updates — ForwardMsgQueue collects Element messages from script execution, wraps them in ForwardMsg containers with delta metadata, and batches them for transmission [Element → ForwardMsg]
- Stream to frontend — WebSocket connection in Server sends batched ForwardMsg protobuf messages to React frontend, handling connection management and error recovery [ForwardMsg]
- Render React components — ThemedApp processes ForwardMsg messages, deserializes protobuf to JavaScript objects, and renders appropriate React components (widgets, charts, text) with current values [ForwardMsg]
- Handle user interactions — Widget components capture user input (clicks, text entry, selections) and send ScriptRequest messages with updated widget values back to Python via WebSocket
- Update session state — Backend receives ScriptRequest, extracts widget values, updates SessionState dictionary with new values, and triggers script re-execution to reflect changes [ScriptRequest → SessionState]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
lib/streamlit/proto/ForwardMsg.protoprotobuf message with oneof fields: new_session, session_state_changed, session_event, page_config_changed, page_info_changed, delta containing Element protobuf with specific widget/display types
Created when user script calls st.* functions, serialized to protobuf bytes, sent over WebSocket, deserialized in React and converted to component props
lib/streamlit/runtime/state/session_state.pydict-like object mapping widget keys (str) to their current values (any JSON-serializable type), with change tracking via filtered_state dict
Initialized empty at session start, populated when widgets created, updated when user interacts, persisted across script reruns to maintain UI state
lib/streamlit/proto/Element.protoprotobuf oneof with fields for each UI component: text, dataframe, chart, widget, etc., each containing component-specific configuration and data
Generated when st.* functions execute, wrapped in ForwardMsg delta, transmitted to frontend, converted to React component props
lib/streamlit/runtime/scriptrunner/script_requests.pydataclass with fields: rerun_data containing widget_states dict, page_script_hash str, script_run_id str
Created when user interacts with widgets or navigation, queued for script runner, consumed to trigger script re-execution with updated state
frontend/component-lib/src/ArrowTable.tswrapper around Apache Arrow Table with typed accessors for columns, rows, and metadata, plus convenience methods for data access
Created from pandas DataFrames via pyarrow serialization, transmitted as binary data, deserialized in frontend for efficient tabular data display
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
In-memory dictionary storing widget values across script reruns, keyed by widget ID with JSON-serializable values
Memory and disk-based cache for @st.cache_data results, using function signature hashing for key generation with TTL expiration
Temporary storage for user-uploaded files with automatic cleanup, indexed by unique file IDs for session-scoped access
Feedback Loops
- Reactive Script Execution (training-loop, reinforcing) — Trigger: User interacts with any widget (slider, button, text input). Action: ScriptRunner re-executes entire Python script from top to bottom with updated widget values in SessionState. Exit: Script execution completes and UI updates are sent to frontend.
- WebSocket Reconnection (retry, balancing) — Trigger: WebSocket connection drops due to network issues or server restart. Action: ConnectionManager attempts to reconnect with exponential backoff, showing connection status to user. Exit: Connection successfully re-established or user navigates away.
- File Change Detection (polling, reinforcing) — Trigger: FileWatcher detects Python script modifications on disk. Action: Server triggers script reload and re-execution, sending updated UI to all connected clients. Exit: No more file changes detected within polling interval.
Delays
- Script Compilation (compilation, ~~100ms) — Python bytecode compilation and module import resolution blocks script execution start
- WebSocket Message Batching (batch-window, ~~16ms) — UI updates are collected and sent in batches to reduce WebSocket overhead and improve rendering performance
- Cache Disk Persistence (cache-ttl, ~configurable) — Cache writes to disk happen asynchronously to avoid blocking script execution
Control Points
- server.enableCORS (feature-flag) — Controls: Whether cross-origin requests are allowed to the Streamlit server. Default: false
- server.maxUploadSize (threshold) — Controls: Maximum file size allowed for uploads via st.file_uploader widget. Default: 200MB
- runner.magicEnabled (feature-flag) — Controls: Whether bare expressions are automatically displayed (magic commands). Default: true
- theme.base (architecture-switch) — Controls: UI color scheme (light/dark mode) affecting all components and styling. Default: light
Technology Stack
HTTP/WebSocket server handling frontend asset serving, API endpoints, and persistent WebSocket connections for real-time updates
Frontend UI framework rendering interactive components from protobuf messages, managing component state and user interactions
Columnar data serialization for efficient transfer of pandas DataFrames from Python to TypeScript for table/chart display
Binary serialization format for all UI messages between Python backend and React frontend, ensuring type safety and performance
Type-safe frontend development with strong typing for protobuf message handling and React component props
File system monitoring for automatic script reload when Python files change during development
Key Components
- ScriptRunner (executor) — Executes user Python scripts in isolated environments, capturing st.* function calls and handling script lifecycle including imports, reruns, and error handling
lib/streamlit/runtime/scriptrunner/script_runner.py - ForwardMsgQueue (dispatcher) — Queues and batches UI update messages from script execution, handles message ordering and ensures consistent delivery to WebSocket clients
lib/streamlit/runtime/forward_msg_queue.py - ConnectionManager (adapter) — Manages WebSocket connection lifecycle between React frontend and Python backend, handles reconnection, message routing, and connection state
frontend/connection/src/ConnectionManager.ts - ThemedApp (orchestrator) — Root React component that manages global app state, theme switching, message handling from backend, and coordinates rendering of all UI elements
frontend/app/src/ThemedApp.tsx - Server (gateway) — Tornado-based HTTP/WebSocket server that serves the React frontend, handles file uploads, manages WebSocket connections, and bridges frontend-backend communication
lib/streamlit/web/server/server.py - CacheDataAPI (optimizer) — Implements @st.cache_data decorator that memoizes expensive function calls using hashing of inputs, with TTL, size limits, and cache invalidation
lib/streamlit/runtime/caching/cache_data_api.py - ComponentRegistry (registry) — Manages custom components by mapping component names to their implementations, handling component lifecycle and frontend-backend communication
lib/streamlit/components/v1/component_registry.py - FileManager (store) — Handles file upload storage, cleanup, and access via unique file IDs, managing temporary file lifecycle and memory usage
lib/streamlit/runtime/uploaded_file_manager.py
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Fullstack Repositories
Frequently Asked Questions
What is streamlit used for?
Transforms Python scripts into interactive web apps with real-time updates streamlit/streamlit is a 8-component fullstack written in Python. Data flows through 7 distinct pipeline stages. The codebase contains 1963 files.
How is streamlit architected?
streamlit is organized into 4 architecture layers: User Script Runtime, Message Processing, WebSocket Server, React Frontend. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through streamlit?
Data moves through 7 stages: Parse user script → Execute script with state → Queue UI updates → Stream to frontend → Render React components → .... Data flows from user Python scripts through protobuf serialization to React components. When users run `streamlit run script.py`, the backend executes the script, capturing st.* function calls as ForwardMsg protobuf messages. These messages stream via WebSocket to the React frontend, which renders them as interactive components. When users interact with widgets, the frontend sends widget values back via WebSocket, triggering script re-execution with updated SessionState, creating a reactive feedback loop. This pipeline design reflects a complex multi-stage processing system.
What technologies does streamlit use?
The core stack includes Tornado (HTTP/WebSocket server handling frontend asset serving, API endpoints, and persistent WebSocket connections for real-time updates), React (Frontend UI framework rendering interactive components from protobuf messages, managing component state and user interactions), Apache Arrow (Columnar data serialization for efficient transfer of pandas DataFrames from Python to TypeScript for table/chart display), Protocol Buffers (Binary serialization format for all UI messages between Python backend and React frontend, ensuring type safety and performance), TypeScript (Type-safe frontend development with strong typing for protobuf message handling and React component props), Watchdog (File system monitoring for automatic script reload when Python files change during development). A focused set of dependencies that keeps the build manageable.
What system dynamics does streamlit have?
streamlit exhibits 3 data pools (SessionStateStorage, CacheStorage), 3 feedback loops, 4 control points, 3 delays. The feedback loops handle training-loop and retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does streamlit use?
4 design patterns detected: Reactive Programming Model, Protobuf Message Streaming, Decorator-Based Caching, Widget State Persistence.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.