Hotwire over heavy SPA: scope and trade-offs
Audience
CTOs, heads of product, and engineering leads working with Ruby on Rails back ends and React/Vue front ends.
Problem statement
Teams maintaining separate front-end and back-end codebases often duplicate routing, validation, and state. Build pipelines and large JavaScript bundles can increase deployment complexity and time-to-interactive.
Core approach (Hotwire)
Hotwire is a server-first pattern for Rails that renders HTML on the server and updates pages incrementally in the browser.
Turbo Frames: target partial page regions for replacement.
Turbo Streams: send create, update, or destroy events over Server-Sent Events or WebSockets to update subscribed views.
Stimulus: attach small behaviors to HTML elements without a front-end framework.
SPA “islands”: keep React/Vue only for components that require complex client-side state.
Suitable use cases
- Admin and back-office CRUD.
- Tables with filters and pagination.
- Dashboards, notifications, activity feeds.
- Wizard flows and multi-step forms.
Cases where an SPA may remain appropriate
- Graphics or canvas-heavy editors.
- Offline-first applications with substantial client-side state.
- Client-side media processing.
Architecture overview
- Controllers render HTML; the browser swaps content into defined frame regions.
- Streams broadcast model changes to connected clients for live updates.
- Stimulus controllers provide focused behaviors for forms and interactions.
- When needed, a SPA component can mount within a frame and receive server data.
Incremental migration plan
- Audit current screens by interaction complexity and data freshness.
- Select a small set of form- or table-centric screens.
- Replace JSON + client rendering with server-rendered responses.
- Wrap swap regions in
<turbo-frame>. - Add Turbo Streams for background updates.
- Remove unused SPA routes and dependencies to reduce bundle size.
- Track time-to-interactive, pull-request lead time, and error rates before and after changes.
Operational considerations
Security: Rails provides CSRF and session handling by default.
Caching: fragment caching with cache keys and digests for frequently rendered regions.
Deployments: a single codebase and CI pipeline can reduce coordination overhead.
Observability: server-side rendering centralizes logs and metrics.
Common questions
UX parity: Frames and Streams can support real-time and optimistic interfaces; SPA components can be retained where necessary.
Rewrite risk: Migration can proceed screen by screen with fallbacks.
Team ramp-up: Rails developers can adopt Turbo and Stimulus with limited changes to existing controller and view patterns.