Reflex Logo
Blog
Open Source
Squares Vertical DocsSquares Vertical Docs

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 TeamReflex Team

Image for blog post: Upgrading Reflex Apps from 0.8 to 0.9

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.

ChangeWhat to do
Database deps are now an extrapip install 'reflex[db]~=0.9.0' and set db_url explicitly
state_auto_setters defaults to FalseDefine set_* event handlers explicitly, or opt back in temporarily
Production runs on a single portAccess --env prod apps on --frontend-port (default 3000)
App.overlay_component removedUse extra_app_wraps
rx.Base and PydanticV1 removedMigrate to dataclasses or Pydantic V2
App.process_background removedUse app.event_processor
codeblock in rx.markdown removedUse pre
reflex-enterprise usersUpgrade 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_componentextra_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.markdownpre:

App.process_backgroundapp.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_substatesState.get_substates()
  • Event.token removed — the token lives on EventContext
  • Event.substate_tokenEvent.state_cls
  • StateManager.create(state=...) no longer takes a state= kwarg
  • fix_events() and get_hydrate_event() removed
  • AppHarness lost state_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 functions
  • backend_path config (#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.

The Unified Platform to Build and Scale Enterprise AppsDescribe your idea, and let AI transform it into a complete, production-ready Python web application.
CTA Card
Built with Reflex