Upgrading Reflex Apps from 0.8 to 0.9
A step-by-step migration guide for upgrading your Reflex app to v0.9.0, covering the new optional database extra, single-port production builds, the auto-setter change, and removed APIs.
Reflex Team
v0.9.0 moves event processing to the backend, makes database support an optional extra, collapses production into a single port, and turns off auto-generated state setters by default. Here's what to change.
| Change | What to do |
|---|---|
| Database deps are now an extra | pip install 'reflex[db]~=0.9.0' and set db_url explicitly |
state_auto_setters defaults to False | Define set_* event handlers explicitly, or opt back in temporarily |
| Production runs on a single port | Access --env prod apps on --frontend-port (default 3000) |
App.overlay_component removed | Use extra_app_wraps |
rx.Base and PydanticV1 removed | Migrate to dataclasses or Pydantic V2 |
App.process_background removed | Use app.event_processor |
codeblock in rx.markdown removed | Use pre |
reflex-enterprise users | Upgrade to >= 0.7.0.post1 |
pydantic, sqlmodel, and alembic are no longer base dependencies. If you use rx.Model or any database helpers, install the db extra:
Or in pyproject.toml:
db_url no longer defaults to a local SQLite file. Declare it in rxconfig.py:
state_auto_setters defaults to False, so Reflex no longer generates set_count for you.
Before:
After:
If a state field has many call sites, you can opt back in temporarily:
This is deprecated and emits a warning. Don't reach for it as a long-term solution — define explicit handlers and remove the flag before v1.0.
The --single-port flag is gone — --env prod now always serves frontend and backend on one port.
The frontend is served by Starlette StaticFiles. Default ports depend on the running mode:
- Fullstack (frontend + backend, the default): both share
--frontend-port(3000) - Frontend only:
--frontend-port(3000) - Backend only:
--backend-port(8000)
Update any reverse proxy or load balancer that split traffic across separate frontend and backend ports.
If you call prerequisites.check_running_mode() in tooling, it now returns a single RunningMode enum (FRONTEND_ONLY, BACKEND_ONLY, FULLSTACK) instead of a (frontend, backend) tuple.
App.overlay_component → extra_app_wraps:
extra_app_wraps is a dict[tuple[int, str], Callable[[bool], Component | None]] — keyed by a (priority, name) tuple, with a callable that receives a stateful: bool and returns the wrapper component (or None). Wrappers must render their children, so use rx._x.memo to declare one:
rx.Base and PydanticV1 are gone. Migrate model classes to dataclasses or Pydantic V2. rx.State is unaffected — it moved off Pydantic in 0.8.
codeblock in rx.markdown → pre:
App.process_background → app.event_processor. App._background_tasks becomes App.event_processor._tasks.
_substate_key / _split_substate_key are deprecated. Use rx.BaseStateToken to address state from outside an event handler — for example with app.modify_state:
Other internal renames:
State.class_substates→State.get_substates()Event.tokenremoved — the token lives onEventContextEvent.substate_token→Event.state_clsStateManager.create(state=...)no longer takes astate=kwargfix_events()andget_hydrate_event()removedAppHarnessloststate_manager,get_state(),set_state(),modify_state(),poll_for_clients(),_reset_backend_state_manager()— drive state through events in tests instead
rx.upload_files_chunk(#6190) — streams chunks instead of buffering whole files@rx._x.memo(#6192, experimental) — JS-level memoization for components and pure functionsbackend_pathconfig (#6338) — prefix backend routes for path-based proxies- In-memory state expiration (#6201) and a Redis state-expiry event (#6194)
- Recharts
Defs(#6322) and dropdown cells in the data editor (#6139)
See the roadmap for what's coming next.
More Posts

Make sankey diagram flows with Python, R, Excel. Sankey plot, sankey chart, and sankey graph examples with Plotly, networkD3. Complete guide for May 2026.

We benchmarked computer use against auto-generated API endpoints on the same admin panel. 53 steps and 551k tokens vs 8 calls and 12k tokens.

We benchmarked browser-use vision agents against auto-generated API endpoints on the same Reflex app. 47 steps and 495k tokens vs 8 calls and 12k tokens.