ActionCable and Turbo Streams: Building Real-Time Features the Rails Way
Learn how ActionCable and Turbo Streams enable real-time Rails applications without abandoning the framework's conventions.
Why Real-Time Features Matter Now
By 2026, users expect instantaneous feedback. Whether you're building a collaborative tool, a live dashboard, or a notification system, latency kills engagement. For Rails developers, the answer has evolved significantly since WebSocket support arrived in Rails 5. Today's combination of ActionCable and Turbo Streams offers a pragmatic path to real-time features without abandoning Rails conventions or requiring separate frontend frameworks.
The beauty of this approach is that you stay within the Rails ecosystem. You're not context-switching between JavaScript frameworks, managing API versioning complexity, or maintaining parallel codebases. Your server-side logic remains in Ruby, your HTML rendering uses ERB or Haml, and your asset pipeline handles the rest.
ActionCable: Rails' WebSocket Layer
How ActionCable Works
ActionCable provides a framework for handling persistent connections between clients and your Rails server. Think of it as a pub/sub (publish/subscribe) system built into Rails. When a user opens your application, ActionCable establishes a WebSocket connection. From that point, your server can push updates to specific users, user groups, or broadcast to everyone without waiting for HTTP requests.
ActionCable uses channels to organize subscriptions. A user might subscribe to a "ChatChannel" or "NotificationChannel." When something happens on the server—a new message, a status update, a database change—you broadcast to that channel, and all subscribed clients receive the update immediately.
Setting Up ActionCable in Your Rails App
ActionCable comes bundled with Rails 5.0 and later, so if you're running Rails 7.1 or 8.0 (both stable and recommended for 2026), you already have it. Configuration is straightforward:
- Configure your WebSocket URL in config/cable.yml. For development, the defaults work fine. For production, you'll point to your production server or a managed service like Heroku or AWS.
- Define channels in app/channels. A basic channel inherits from ApplicationCable::Channel.
- Use stream_from or stream_for to listen for broadcasts within your channel's subscribed method.
- Broadcast from your controllers, models, or jobs using ActionCable.server.broadcast or the shorthand broadcast_to method.
Here's a simple example: a notification channel that broadcasts to a specific user:
app/channels/notification_channel.rb:class NotificationChannel < ApplicationCable::Channel
def subscribed
stream_for current_user
end
end
Broadcasting from a controller or job:NotificationChannel.broadcast_to(@user, { message: "Your report is ready" })
Turbo Streams: The HTML-Over-HTTP Companion
Why Turbo Streams Matter
Turbo Streams extend Rails' traditional HTML-over-HTTP approach by allowing your server to send targeted DOM updates to the browser without a full page reload. Rather than returning JSON and writing JavaScript to update the UI, you return a Turbo Stream—an HTML fragment containing instructions like "replace this element" or "append to that list."
This philosophy aligns perfectly with Rails' design: keep logic on the server, keep views in templates. Your JavaScript footprint shrinks dramatically.
ActionCable + Turbo Streams: The Combination
The magic happens when you combine these two. ActionCable gives you the real-time transport (WebSocket). Turbo Streams give you the updates (DOM mutations). Together, they let you broadcast HTML updates to multiple clients simultaneously.
Example: A live comment feed
When a user posts a comment, you broadcast a Turbo Stream that appends the new comment HTML to everyone viewing the same post. No JSON parsing, no frontend JavaScript logic—just server-side rendering and a broadcast instruction:
broadcast_to(@post, action: :append, target: "comments", partial: "comments/comment", locals: { comment: @comment })
Every client subscribed to that post receives the stream, and Turbo automatically updates their DOM.
Practical Implementation Considerations
Scaling and Connection Management
In production, a single Rails server can't handle thousands of concurrent WebSocket connections efficiently. You'll need a message broker. Redis is the standard choice, and ActionCable integrates seamlessly with it. Configure config/cable.yml to use Redis in production, and your app automatically scales across multiple server instances.
For North American businesses expecting growth, consider managed options: Heroku's built-in Redis, AWS ElastiCache, or dedicated Redis services like Redis Cloud. This offloads infrastructure management and ensures reliability.
Authentication and Security
ActionCable respects your Rails session. The current_user helper works automatically in your channels. However, ensure you:
- Validate user permissions within channel actions. Don't assume a subscription means authorization.
- Use stop_stream or stop_stream_for to unsubscribe users when they lose access.
- Enable WebSocket origin checking in production to prevent CSRF attacks.
- Use encrypted connections (wss://, not ws://) in production.
Database and Background Jobs
Broadcasting often happens in background jobs. Use Sidekiq or Rails' built-in async jobs to avoid blocking request handling. A user creates a resource, a job processes it, and when complete, the job broadcasts the update. This keeps your response times snappy.
Common Pitfalls and Solutions
Latency expectations: Real-time doesn't mean instant. Network latency, server processing, and browser rendering add overhead. For most applications, sub-second updates are sufficient. If you need true millisecond-level latency, you're venturing into specialized territory (financial trading, gaming) where Rails might not be the right fit.
Connection drops: Mobile users lose WiFi, proxies timeout connections. Turbo handles reconnection automatically, but design your UI to gracefully handle temporary disconnects. Show a "reconnecting" indicator.
Testing: Testing ActionCable channels requires specific setup. Use ActionCable::Channel::TestCase for unit tests, and consider integration tests with Rails' built-in WebSocket test helpers.
When to Use This Approach
ActionCable and Turbo Streams excel for dashboards, collaborative tools, live notifications, real-time chat, and activity feeds. They're less suitable for performance-critical, high-frequency updates (trading floors, real-time analytics). For most business applications, this stack is ideal.
Wrapping Up
Rails' approach to real-time features respects the framework's philosophy: convention over configuration, keep logic server-side, minimize frontend complexity. By 2026, ActionCable and Turbo Streams are mature, battle-tested technologies used by companies at scale. They let you deliver modern user experiences without abandoning Rails' productivity advantages.
If your team is considering a real-time Rails upgrade or building a new feature, this is the time to invest in understanding these tools deeply. The learning curve is gentle, and the payoff—faster development cycles and happier users—is substantial.
Ready to implement real-time features in your Rails application? ElevenClicks specializes in Rails modernization and performance optimization across Canada and North America. Our team has shipped production ActionCable implementations for financial platforms, SaaS tools, and collaborative applications. Let's discuss how real-time capabilities can elevate your product. Contact us today for a technical consultation.
Working on something similar?
ElevenClicks helps Canadian businesses build ruby on rails solutions that actually work. Book a free 30-minute call — no pitch, just honest advice.
Ontario-based · Canadian timezone · No offshore handoffs