understanding-streamlit-architecture

작성자: streamlit

Streamlit의 내부 아키텍처를 설명하며, 백엔드 런타임, 프론트엔드 렌더링, WebSocket 통신을 포함합니다. 계층 간 문제를 디버깅할 때 사용하세요.

npx skills add https://github.com/streamlit/streamlit --skill understanding-streamlit-architecture

Understanding Streamlit architecture

Streamlit is a client-server application with bidirectional WebSocket communication using Protocol Buffers. Use this file as a quick mental model and navigation index; use references/backend.md, references/frontend.md, and references/communication.md for implementation details.

Concepts glossary

ConceptDescriptionKey files
CommandAny function exposed in Streamlit's public API (st.* namespace). Commands can create elements/widgets, control execution flow, or configure app behavior.lib/streamlit/delta_generator.py, lib/streamlit/elements/, lib/streamlit/commands/
ElementUmbrella term for all UI components in Streamlit: widgets, containers, and display elements. Represented in Element.proto as a oneof union of ~50+ types.proto/streamlit/proto/Element.proto, lib/streamlit/elements/
WidgetInteractive element (button, slider, text_input) that triggers reruns on user interaction. Value accessible via return value or st.session_state. Some elements become widgets conditionally (e.g., dataframe/chart with on_select).lib/streamlit/elements/widgets/, frontend/lib/src/components/widgets/
Display ElementNon-interactive element (text, markdown, image, chart) that renders content without triggering reruns by itself.lib/streamlit/elements/, frontend/lib/src/components/elements/
ContainerLayout block that groups elements spatially (sidebar, columns, expander, tabs, form). Represented as BlockNode in the element tree.lib/streamlit/elements/layouts.py, Block.proto
DeltaGeneratorThe st object; API entry point that queues UI deltas. Uses mixin pattern to compose all st.* commands.lib/streamlit/delta_generator.py
Session StatePer-session dictionary (st.session_state) persisting data across reruns. Stores widget values and user variables.lib/streamlit/runtime/state/session_state.py
RerunRe-execution of the user script for the current page. Triggered by widget interactions, st.rerun(), file changes, or fragment timers. Rebuilds the element tree while preserving session state.lib/streamlit/runtime/scriptrunner/script_runner.py, lib/streamlit/commands/execution_control.py
FormContainer (st.form) that batches widget inputs, deferring reruns until form submission.lib/streamlit/elements/form.py, WidgetStateManager.ts
FragmentDecorator (@st.fragment) enabling partial reruns of specific UI sections without full script re-execution.lib/streamlit/runtime/fragment.py
CachingDecorators (@st.cache_data, @st.cache_resource) that memoize function results to avoid redundant computation.lib/streamlit/runtime/caching/
PagesMultipage app system using st.navigation() and st.Page() or auto-discovery from pages/ directory.lib/streamlit/navigation/, lib/streamlit/runtime/pages_manager.py
ConfigApp configuration via .streamlit/config.toml controlling server, client, and theme settings.lib/streamlit/config.py, lib/streamlit/config_option.py
ThemingCustomizable UI themes (Light/Dark/Custom) defined in config or via theme editor.lib/streamlit/runtime/theme_util.py, frontend/lib/src/theme/
SecretsSecure credential storage via .streamlit/secrets.toml (local) or platform settings (deployed). Accessed via st.secrets.lib/streamlit/runtime/secrets.py
ConnectionDatabase/service abstraction (st.connection) with built-in caching and secrets integration.lib/streamlit/connections/
Custom ComponentsUser-built extensions using React/iframe. v1 (legacy): declare_component() API. v2 (current): Bidirectional components with improved state management.frontend/component-lib/, frontend/component-v2-lib/, lib/streamlit/components/v1/, lib/streamlit/components/v2/
Static File ServingFiles in static/ directory served directly via /app/static/* (when static serving is enabled).lib/streamlit/web/server/server.py, lib/streamlit/web/server/starlette/starlette_routes.py
App TestingTesting framework (AppTest) for simulating user interactions and inspecting rendered output.lib/streamlit/testing/

Core mental model

flowchart TB
    subgraph Backend["Backend (Python)"]
        Script[User Script]
        DG[DeltaGenerator]
        Runtime[Runtime/AppSession]
    end

    subgraph Protocol["WebSocket + Protobuf"]
        FM[ForwardMsg]
        BM[BackMsg]
    end

    subgraph Frontend["Frontend (React)"]
        App[App.tsx]
        Tree[AppRoot Tree]
        Renderer[ElementNodeRenderer]
        WSM[WidgetStateManager]
    end

    Script --> DG
    DG --> FM
    FM --> App
    App --> Tree
    Tree --> Renderer
    Renderer --> WSM
    WSM -->|User interaction| BM
    BM --> Runtime
    Runtime -->|Rerun| Script

Key insight: Script execution is rerun-driven: most widget interactions trigger reruns (full app or fragment-scoped). State persists via st.session_state and caching decorators.

Execution model

Streamlit's execution model differs from traditional web frameworks:

Rerun triggers:

  1. Widget interaction: User clicks button, moves slider, etc.
  2. Source code change: File watcher detects script modification
  3. st.rerun(): Explicit programmatic rerun
  4. Fragment timer: @st.fragment(run_every=...) periodic reruns

Execution order nuances:

  • Scripts execute top-to-bottom on every rerun
  • Callbacks first: on_change/on_click handlers run before the main script body
  • Fragments typically isolate reruns: Widget interactions inside @st.fragment usually rerun only that fragment
  • Control flow exceptions: st.stop(), st.rerun(), st.switch_page() raise exceptions to halt/redirect execution

Session isolation:

  • Each browser tab = separate AppSession with its own SessionState
  • Refreshing the page creates a new session (unless reconnecting within TTL)
  • No shared state between sessions (use external storage for multi-user state)

What persists across reruns (within a session):

  • st.session_state values
  • Cached function results (@st.cache_data, @st.cache_resource)
  • Uploaded files
  • Fragment registrations

What resets on each rerun:

  • Local variables in script
  • Widget return values (re-read from SessionState)
  • Element tree (rebuilt from scratch, then diffed)

Architecture layers

Backend (Python)

ComponentFilePurpose
Runtimelib/streamlit/runtime/runtime.pySingleton managing app lifecycle and sessions
AppSessionlib/streamlit/runtime/app_session.pyPer-browser-tab: ScriptRunner + SessionState + ForwardMsgQueue
ScriptRunnerlib/streamlit/runtime/scriptrunner/script_runner.pyExecutes user scripts in separate thread
DeltaGeneratorlib/streamlit/delta_generator.pyAPI entry point using mixin pattern
SessionStatelib/streamlit/runtime/state/session_state.pyWidget values and user variables
Elementslib/streamlit/elements/Backend implementation of st.* commands

For backend deep dive: See references/backend.md

Frontend (TypeScript/React)

ComponentFilePurpose
Appfrontend/app/src/App.tsxCentral orchestrator
AppRootfrontend/lib/src/render-tree/AppRoot.tsImmutable element tree with 4 containers
ElementNodeRendererfrontend/lib/src/components/core/Block/ElementNodeRenderer.tsxMaps protos to React components
WidgetStateManagerfrontend/lib/src/WidgetStateManager.tsWidget state, forms, query params
ConnectionManagerfrontend/connection/src/ConnectionManager.tsWebSocket state machine

For frontend deep dive: See references/frontend.md

Communication (Protobuf)

ProtoPurpose
ForwardMsg.protoServer to client: deltas, session events, navigation
BackMsg.protoClient to server: rerun requests with widget states
Element.proto~50+ element types in oneof type union
WidgetStates.protoWidget values: trigger_value, string_value, bool_value, etc.

Location: proto/streamlit/proto/

For protocol deep dive: See references/communication.md

Essential concepts (quick map)

  • Layout system: Width/height parameters for elements, flexbox containers, and responsive sizing.
  • Script rerun model: Widget interaction -> BackMsg (ClientState) -> backend updates SessionState -> script rerun -> ForwardMsg deltas.
    • Deep dive: references/communication.md#widget-interaction-to-script-rerun
  • Delta path system: Elements are addressed by delta paths (for example [0, 2, 3]) to support efficient tree updates.
    • Deep dive: references/communication.md#delta-ui-changes
  • active_script_hash semantics: ForwardMsg.metadata.active_script_hash scopes node ownership across multipage and fragment reruns.
    • Deep dive: references/communication.md#forwardmsg-metadata-active_script_hash
  • Element tree structure: Frontend AppRoot maintains main, sidebar, event, and bottom containers with BlockNode/ElementNode.
    • Deep dive: references/frontend.md#element-tree-frontendlibsrcrender-tree
  • Element identity semantics: Delta paths decide where a node lives; element IDs decide whether stateful elements can reconnect to prior state after remounts.
    • Deep dive: references/element-identity.md
  • Fragments (@st.fragment): Fragment interactions usually trigger fragment-scoped reruns and update only affected regions.

Element identity

  • Delta path controls where a node is placed in the render tree.
  • Element ID controls whether a stateful element can reconnect to prior state after remounts.
  • Widgets use the ID to connect frontend WidgetStateManager state, BackMsg.WidgetStates, backend SessionState, callbacks, and st.session_state.
  • Some non-widgets also use IDs for frontend-only reconstruction (for example chart view state or media autoplay guards).
  • Delta-path changes can remount elements, but a stable element.id can still let React preserve a leaf when it remains under the same rendered parent list.

Deep dive: references/element-identity.md

Key implementation patterns

  • Backend mixin composition: DeltaGenerator composes st.* API via mixins.
    • Deep dive: references/backend.md#deltagenerator-libstreamlitdelta_generatorpy
  • Frontend visitor pattern: Render-tree updates/staleness cleanup use visitors.
    • Deep dive: references/frontend.md#visitor-pattern
  • Message deduplication: ForwardMsg.hash + ref_hash with frontend ForwardMsgCache reduces bandwidth.
    • Deep dive: references/communication.md#message-caching

Quick reference: adding features

  1. Proto definition: proto/streamlit/proto/<Element>.proto
  2. Register in Element.proto: Add to oneof type
  3. Backend mixin: lib/streamlit/elements/<element>.py
  4. Frontend component: frontend/lib/src/components/elements/<Element>/ or frontend/lib/src/components/widgets/<Element>/ (depending on element vs widget)
  5. Register in ElementNodeRenderer: Add case to switch statement
  6. Compile protos: make protobuf

See wiki/new-feature-guide.md for a detailed implementation guide.

Maintaining this documentation

When making changes that impact any of the concepts documented here (Runtime, AppSession, DeltaGenerator, element tree, communication protocol, element identity, etc.), update the relevant sections in this skill's files (SKILL.md, references/backend.md, references/frontend.md, references/communication.md, references/element-identity.md) to keep them accurate.

streamlit의 다른 스킬

developing-with-streamlit
streamlit
**[필수]** 모든 Streamlit 작업(Streamlit 애플리케이션 생성, 편집, 디버깅, 미화, 스타일링, 테마 적용, 최적화)에 사용하세요. 또한 필요합니다…
official
addressing-pr-review-comments
streamlit
현재 브랜치의 streamlit/streamlit 저장소에 있는 PR의 모든 유효한 리뷰 코멘트를 처리합니다. 인라인 리뷰 코멘트와 일반 PR(이슈) 코멘트를 모두 포함합니다.
official
checking-changes
streamlit
커밋 전에 포맷, 린트, 타입, 단위 테스트 검사를 실행하여 모든 코드 변경 사항을 검증합니다. 백엔드(Python) 또는 프론트엔드(TypeScript) 작업 후에 사용하세요…
official
discovering-make-commands
streamlit
Streamlit 개발에 사용 가능한 make 명령어를 나열합니다. 빌드, 테스트, 린트 또는 포맷 작업에 사용하세요.
official
finalizing-pr
streamlit
병합을 위해 브랜치 변경 사항을 최종 확정하며, 코드 단순화, 검사 실행, 변경 사항 검토, 필요 시 PR 생성을 수행합니다. 변경 사항을 병합할 준비가 되었을 때 사용하세요.
official
fixing-flaky-e2e-tests
streamlit
불안정한 Playwright e2e 테스트를 진단하고 수정합니다. 테스트가 간헐적으로 실패하거나, 시간 초과 오류가 발생하거나, 스냅샷 불일치가 있거나, 브라우저별 특성을 보일 때 사용하세요.
official
fixing-streamlit-ci
streamlit
현재 브랜치/PR에서 실패한 GitHub Actions CI 작업을 분석하고 수정합니다. CI 검사가 실패하거나, PR 검사에서 오류가 표시되거나, 진단이 필요할 때 사용하세요…
official
generating-changelog
streamlit
두 개의 git 태그 사이에 있는 docs.streamlit.io용 정리된 웹사이트 릴리스 노트를 생성합니다. 새로운 Streamlit 릴리스를 준비하거나 변경 사항을 검토할 때 사용합니다.
official