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

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.

Learn how to build a chat app with LLM in Python with streaming, RAG, and production interfaces. Complete implementation guide for April 2026.