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

  1. Audit current screens by interaction complexity and data freshness.
  2. Select a small set of form- or table-centric screens.
  3. Replace JSON + client rendering with server-rendered responses.
  4. Wrap swap regions in <turbo-frame>.
  5. Add Turbo Streams for background updates.
  6. Remove unused SPA routes and dependencies to reduce bundle size.
  7. 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.