Reflex

Migrating from Plotly Dash to Reflex

When your Dash dashboard grows into a complex application, take control of its interface and interactions. Reflex keeps application state on the server and sends changed values to a React frontend, while your team keeps building in Python.

TL;DR

A Python dashboard alternative for the application you want to build next.

  • Large Dash component trees can add browser-side work on each update. Profile the number of mounted components alongside your callbacks and data pipeline.
  • Reflex keeps application state on the server and sends changed values over a WebSocket. Use conditional rendering to mount expensive content when it is needed.
  • A public development-mode benchmark reported a 215 ms initial load in Reflex versus about six minutes in Dash for a page configured for roughly 17,200 components. The Reflex version initially left collapsed content unmounted.
  • Keep independent Python analysis and Plotly figure code. Rebuild your layout and callback wiring in Reflex's component and state model.
  • Use a screenshot or description of your Dash app as a reference in Reflex Build, then review and test the generated application.

From a Dash prototype to a production app.

Bayesline moved its financial analytics application from Dash to Reflex. Cofounder Sebastian Janisch describes what changed for the team.

Bayesline
50% less code than the same Dash app and easier to read / write / maintain code compared to Dash
Sebastian JanischCofounder · Bayesline
Read the Bayesline case study

Why Dash performance can drop as your app grows

In the benchmark's Dash implementation, mounted components subscribe to a shared browser store. Dispatches notify those subscribers, and mounting or updating many components increases the work. Collapsed content still contributes if it remains mounted.

Developer olincb compared pages containing collapsible checkbox groups. The reported initial-load results below are from development mode. Both pages expose the same groups, but Reflex uses conditional rendering to defer mounting collapsed contents.

Reported component-scaling benchmark · Development mode
WorkloadReflexDash
Initial load · ~5,200 configured components~305 ms~22 s
Initial load · ~17,200 configured components~215 ms~364 s
Write all checkboxes · ~5,200 mounted components~1.2 s~29 s

Reported third-party development-mode results, not a production latency guarantee. Initial loads use different mounting strategies; component counts describe the configured page. The write-all test changes many checkbox values, not a single field.

View the source code and benchmark

What these measurements cover

When all roughly 17,200 components were mounted with Expand all, the Reflex example took about 5.3 seconds. Its shared state context also adds work as mounted content grows. Hiding content with CSS does not automatically unmount it; this example uses rx.cond.

The author recommends pagination, mounting content on demand, and limiting broad updates. Dash also documents caching and callback optimizations. These measurements were not independently reproduced for this page; test your production build with realistic data, network conditions, and concurrency.

Dash benchmark analysisReflex benchmark analysisDash performance guidance

What changes when you migrate, and what doesn't

Start with your data loading, transforms, model calls, and Plotly figures. Independent Python code can often be reused. The interface and its interaction model are the parts you rebuild.

Layout

A tree built from Dash HTML and Core Components becomes a tree of Reflex components. Keep expensive panels conditional and give each screen a clear purpose.

Callbacks

Map Input and Output relationships to methods on a typed Reflex State class. Event handlers update state directly; explicitly preserve validation, dependencies, and background work.

Styling

Bring CSS or use Tailwind classes and CSS-like style props alongside your Python components. Compose layouts around the workflow your users need.

The shortcut

Give Reflex Build a screenshot or description of your current Dash app to scaffold a first pass. Review the generated Python, reconnect services, and test the behavior before production. Build access and export features depend on your plan.

Use screenshots in Reflex Build

Build your next dashboard with Reflex

Choose Reflex when you want to organize complex interactions around explicit Python state, control which parts of the interface are mounted, and extend your dashboard into a custom application. Wrap React libraries when you need specialized UI components.

Plan the transition around existing deployments, authentication, and team knowledge. If you use Dash Enterprise, map the services and controls you rely on before moving a production workflow.

Scroll horizontally to compare both products.

Scroll horizontally to compare →

Reflex and Dash: capabilities and operating responsibilities
DecisionDashReflex
State

Connect component properties with callbacks; browser rendering cost depends on the mounted component tree.

Source

Organize per-session Python state and event handlers on the server; send changed values to the frontend.

Source

Components

Dash Core and HTML Components, custom components, and community packages.

Source

Built-in UI components, Plotly charts, and wrappers for React libraries.

Source

License

Core Dash is MIT licensed. Dash Enterprise is a separate commercial product.

Source

The framework is Apache 2.0 licensed. Build and managed services have separate plans.

Source

Deployment

Self-managed deployment or commercial hosting, including Dash Enterprise.

Source

Managed Reflex hosting or self-host the frontend and Python backend, including in your VPC or on premises.

Source

Compare styling, licensing, and deployment in depth

By the numbers

An open-source foundation you can extend.

Python

Keep your application logic and author the interface in the same language.

See how Reflex works

Frequently asked questions

Performance, migration, and what you can reuse.

Is Reflex a good alternative to Plotly Dash?

Yes, for teams that want a custom application interface and explicit Python state around their analytics. Reuse independent Python logic and Plotly figures while building the surrounding experience in Reflex. Measure your own workload before committing to a performance target.

What are Plotly Dash's limitations?

Large mounted component trees and callbacks that update many components can add browser work. The linked benchmark demonstrates this for a checkbox-heavy page. Performance also depends on data loading, serialization, callback design, and deployment; pagination and lazy mounting can reduce work.

Reflex vs. Dash: what actually changes?

The component and state models. Layouts move from Dash's component tree to Reflex's; callback Input and Output declarations become event handlers on State classes. Independent Python functions are candidates for reuse, with outputs and integration behavior verified during migration.

How do I migrate a Dash app to Reflex?

Extract data loading, transforms, model calls, and figure-building code from UI callbacks. Rebuild one layout and its interactions in Reflex, or use Reflex Build to scaffold from a screenshot. Validate the result, reconnect persistence and access controls, and expand one workflow at a time.

Do I have to rewrite anything in JavaScript?

You can author your application interface and backend logic in Python; Reflex generates the React frontend. Integrating specialized React components may require JavaScript or TypeScript, but you do not need to maintain a separate handwritten React app.

Is Reflex actually free?

The framework is open source under Apache 2.0. You can install it, develop locally, and self-host without paying Reflex for a framework license. Infrastructure has its own costs; Reflex Build, managed hosting, and enterprise services have separate plans.

Start with one command

pip install reflex