Reflex

Take your Streamlit app to production with Reflex.

Build a custom application around the Python logic you already trust. Control your interface, navigation, and interactions with a React frontend generated from Python, without hand-writing a separate React app. Deploy with Reflex or on your own infrastructure.

TL;DR

Reflex is a Python alternative to Streamlit for teams taking an app to production. Updated September 2026.

  • When a Streamlit app outgrows its original dashboard scope, rebuild its interface in Reflex while reusing independent Python logic. Reflex compiles the interface to React without a separate hand-written React frontend.
  • In an internal NBA dashboard benchmark, one Reflex implementation showed the player table in 2.1 seconds versus 15.6 seconds for Streamlit on simulated slow 4G. This measures initial data visibility, not full interactivity.
  • As a Streamlit app spans multiple pages, background jobs, or per-user access rules, developers must coordinate session state and rerun behavior. Reflex gives user actions explicit Python event handlers tied to typed state.
  • Take your prototype into a complete application with Reflex: custom screens, application workflows, and access rules implemented around your users.
  • Streamlit offers Community Cloud and other hosting options. Reflex offers managed hosting or self-hosting on your own infrastructure.

Build the interface your application needs.

When your Streamlit dashboard becomes a daily workflow, take control of the screens, components, and interactions around it.

Style with CSS and Tailwind, component by component.

Style individual components, reuse CSS and Tailwind styles, and compose responsive layouts. Build a branded workspace around the analysis.

Explore responsive styling

Wrap any React component you already rely on.

Extend the interface with React libraries or custom components. Connect their props and events to your Python application.

Explore React components

Give every action its own event handler.

Model drafts, saves, and background work with explicit Python state and event handlers. Give each action a clear place in your application.

Explore Python events

From analysis to action.

Bring your data, record details, and decisions into one workspace.

Teams that moved from Streamlit to Reflex in production.

From e-commerce analytics to cybersecurity and internal tools, hear why these teams chose Reflex for their next application.

With Reflex the code is much more organized and every time the user does something it's more dynamic, more event based.
Mike WoodcockHead of AI & Automation · SellerX
Read the SellerX case study

Reflex vs Streamlit performance: time to visible data

In an internal NBA dashboard benchmark, the Reflex implementation showed the player table in 2.1 seconds on simulated slow 4G. The Streamlit implementation took 15.6 seconds.

NBA dashboard · Simulated slow 4G

Time until data is visible

Lower is better.

Reflex2.13s
Streamlit15.56s
Reported internal benchmark, June 2026. Initial data visibility, not time to full interactivity. Results vary by application and configuration.

All network results and methodology

NBA dashboard time-to-data-visible, median milliseconds
NetworkReflexStreamlit
Local436 ms681 ms
Cable484 ms1,727 ms
Simulated slow 4G2,132 ms15,556 ms

Source: NBA Data App, Production Performance, June 3, 2026. Production-mode apps on one Linux workstation, measured in Chromium with a cold browser cache. Values are medians of 7 local, 5 cable, and 3 slow-4G runs. Cable: 20/5 Mbps and 28 ms RTT. Slow 4G: 1.6/0.75 Mbps, 150 ms RTT, and 4x CPU slowdown. Time to visible data is the later of first contentful paint and table rows entering the DOM.

These supplied results have not been independently reproduced. Caveats:

  • Reflex 0.9.3.post14.dev0 included branch-specific tree-shaking and font-preload changes. The report lists Streamlit's version only as 1.32 or later, without an exact version number.
  • The Reflex app prerendered its first table page.
  • Compression settings differed, so this is not a comparison at compression parity.
  • Initial visibility does not measure full interactivity or throughput. Streamlit filtering latency was not measured.
  • Reflex used more idle server memory (327 MB versus 175 MB PSS) and more memory per held session.

Results depend on the implementation and environment.

Read the benchmark report

Reflex vs Streamlit: the details.

See how each framework approaches custom interfaces, application state, and deployment.

Scroll horizontally to compare both products.

Scroll horizontally to compare →

Reflex and Streamlit: capabilities and operating responsibilities
DecisionStreamlitReflex
Styling and layout

Configure app themes and use layout primitives to organize widgets.

Source

Control CSS at component and global levels. Compose reusable styles and responsive layouts around your workflow.

Source

Custom components

Extend the UI with custom components; Components v2 can integrate directly into the page.

Source

Wrap React libraries or local React components, exposing props and events to your Python application.

Source

Interactions and state

Uses a script rerun model with session state. Forms batch inputs and fragments can rerun independently.

Source

Model user actions with Python event handlers and explicit state. Connect draft edits, saves, and background work to your UI.

Source

Python and the frontend

Author data apps with Python scripts and Streamlit UI commands.

Source

Author the interface and application logic in Python. Reflex compiles the interface to React and runs backend logic in Python.

Source

Deployment

Deploy through Streamlit Community Cloud or other hosting providers.

Source

Choose managed Reflex hosting or self-host the frontend and Python backend on infrastructure you control.

Source

What this comparison covers

Compare how Streamlit and Reflex handle styling, components, interactions, and deployment. The NBA performance example on this page measures one implementation of each framework.

Considering a Streamlit-to-React rewrite?

Build a React-powered interface while continuing to author your application in Python.

Keep the Python that works.

Reflex generates a React frontend from an interface authored in Python. Keep independent calculations, data clients, and Python libraries without maintaining a separate handwritten React application. Specialized components may still need JavaScript or TypeScript.

Rebuild the experience around it.

Migration is a deliberate interface rebuild. Reuse independent Python logic while adapting Streamlit widgets, session state, caching, and rerun-dependent code to the new application.

How Reflex generates your frontend

How to migrate from Streamlit to Reflex

Start with a working slice of your Streamlit app. Preserve the result, improve the experience, and validate it with real users.

  1. Keep a trusted baseline

    Choose one calculation and a fixed dataset. Record the current results and extract reusable Python logic from the Streamlit UI.

  2. Build the application screens

    Compose a queue, record details, and an edit form in Reflex. Map session state and rerun-dependent behavior to explicit events.

  3. Make actions reliable

    Implement authorization and persistent saves. Check invalid input, failed requests, duplicate submissions, and recovery after reload.

  4. Validate, then deploy

    Compare results with the baseline. Test realistic network and concurrency conditions, then deploy with Reflex or self-host.

From a Streamlit callback to a Reflex event handler

Move an approval action from session state into a typed Reflex State. The button still calls Python; Reflex updates the interface from the changed state.

Streamlit

import streamlit as st

if "approved" not in st.session_state:
    st.session_state.approved = False


def approve():
    st.session_state.approved = True


st.button("Approve", on_click=approve)
st.write("Approved" if st.session_state.approved else "Pending")

Reflex

import reflex as rx


class ApprovalState(rx.State):
    approved: bool = False

    @rx.event
    def approve(self):
        self.approved = True


def index():
    return rx.vstack(
        rx.button("Approve", on_click=ApprovalState.approve),
        rx.text(rx.cond(ApprovalState.approved, "Approved", "Pending")),
    )


app = rx.App()
app.add_page(index)

These minimal examples keep approval in session state. A production workflow also needs server-side authorization, database persistence, and error handling.

Deploy on your terms.

Use managed Reflex hosting or run the frontend and Python backend on your own infrastructure. Plan authentication, authorization, monitoring, and capacity for your application.

Explore deployment options

Framework, Build, and hosting: what’s included?

Open-source framework

The Apache 2.0 Python framework is available independently of Build and managed hosting. Your app still depends on Reflex and its other packages.

Explore the framework

Reflex Build

The AI development product generates and edits framework-based apps. Usage, private projects, repository access, and export entitlements belong to your plan.

Explore Build

Hosting and App Management

Managed deployment is an operating service. You can also self-host a framework app, providing its frontend, Python backend, configuration, and maintenance.

Compare hosting options

Enterprise

Enterprise packages and services have separate entitlements. Workspace SSO is distinct from app-user authentication. Authorization, auditing, and private deployment need configuration and an agreed operating plan.

Review plans

Questions about moving from Streamlit.

Production, performance, and what changes when you migrate.

Is Streamlit production-ready?

Streamlit supports deployed applications. Production readiness depends on your app’s access controls, reliability, performance, and operating requirements. Choose Reflex when you want direct control over a custom interface, navigation, and application workflows while keeping your team in Python.

Where does Streamlit hit limits in production?

Streamlit uses a script rerun model, with session state carrying values between runs. Forms batch inputs and fragments limit reruns to part of the app. As workflows span multiple pages, background jobs, and per-user access rules, developers must coordinate state, job lifecycles, and authorization across those execution paths. Reflex models user actions with explicit Python event handlers tied to typed state, giving draft edits, saves, and background work their own place in the application. Authorization still needs to be implemented in either framework.

Do I need to rewrite my Streamlit app in React?

With Reflex, you author the interface in Python and Reflex generates React. You still rebuild the Streamlit UI and adapt its interactions and state. You do not need a separate handwritten React application; specialized custom components may require JavaScript or TypeScript.

How much of my existing Python code can I reuse?

Independent calculations, data clients, models, and Python libraries are candidates for reuse. Separate them from Streamlit UI calls, caching, and session state, then validate their outputs when called from Reflex event handlers.

How customizable is the Reflex UI?

Style individual components with CSS, reuse styles, and build responsive layouts with grid and flex. Add dynamic routes and wrap React libraries when you need specialized components. Streamlit also supports theming and custom components; Reflex makes whole-application composition part of its Python model.

Will Reflex solve my Streamlit performance issues?

Measure your workload. The NBA example on this page shows lower time to visible data for one optimized Reflex implementation. It does not establish faster interactions or greater capacity for every app. Profile data access, rendering, network conditions, and concurrency before and after migration.

Your Python. A more capable application.

Bring a workflow you want to improve. Build the next version with Reflex.