DEV Community

Germán Alberto Gimenez Silva
Germán Alberto Gimenez Silva

Posted on • Originally published at rubystacknews.com on

The Reality of IO-Bound Rails Applications

February 20, 2025

It is often said that a Ruby on Rails application is IO-bound, meaning that the primary performance bottleneck is waiting for external resources such as the database, caching systems, or APIs. This assumption has led many teams to adopt performance strategies that may not yield the expected results. But is your Rails app really IO-bound? Let’s take a closer look.


Need Expert Ruby on Rails Developers to Elevate Your Project?

Fill out our form! >>


Need Expert Ruby on Rails Developers to Elevate Your Project?


Understanding IO-Bound vs. CPU-Bound

An IO-bound application is one where performance is limited by waiting on external operations—database queries, Redis calls, or external HTTP requests. A CPU-bound application, on the other hand, spends most of its time doing computations, such as rendering complex templates, executing business logic, or processing large datasets in memory.

Rails apps tend to involve a lot of database interactions, so it’s easy to assume they’re IO-bound. But in practice, many performance issues arise from inefficient Ruby code rather than slow external services.

Measuring IO vs. CPU Bottlenecks

The best way to determine whether your app is IO-bound or CPU-bound is to measure it.

  • Logging ActiveRecord Queries – If an application is truly IO-bound, logs should reveal long-running queries or excessive query counts per request.
ActiveSupport::Notifications.subscribe("sql.active_record") do |_, start, finish, _, payload|
  duration = (finish - start) * 1000
  Rails.logger.info("Query: #{payload[:sql]} (#{duration.round(2)}ms)")
end
Enter fullscreen mode Exit fullscreen mode
  • Using Stackprof for CPU Profiling – If requests are slow but database queries are fast, the issue likely lies in Ruby execution.
require 'stackprof'
StackProf.run(mode: :wall, out: 'tmp/stackprof.dump') do
  # Your slow request
end
Enter fullscreen mode Exit fullscreen mode

Common CPU-Bound Bottlenecks

Even in applications that frequently interact with a database, CPU bottlenecks are common. Some examples include:

  • JSON Serialization – Transforming large ActiveRecord objects into JSON can be expensive.
render json: users.map { |user| user.as_json(only: [:id, :name, :email]) }
Enter fullscreen mode Exit fullscreen mode
  • Expensive View Rendering – If templates perform too many calculations (e.g., calling methods on each object in a collection), rendering can slow down significantly.
<% users.each do |user| %>
  <%= expensive_method(user) %>
<% end %>
Enter fullscreen mode Exit fullscreen mode
  • Inefficient Iterations – Many performance issues come from inefficient loops over large collections.
users.each { |user| user.update(status: 'active') }
Enter fullscreen mode Exit fullscreen mode

Instead, use bulk updates:

User.update_all(status: 'active')
Enter fullscreen mode Exit fullscreen mode

Conclusion

Not every Rails app is IO-bound, and optimizing under that assumption can lead to misguided performance improvements. Before reaching for background jobs, caching layers, or database indexing, it’s crucial to measure and determine the true source of slow performance.

This article is based on the original piece: The Mythical IO-Bound Rails App, with some additional examples to illustrate common performance pitfalls.

Understanding the actual bottlenecks in your Rails application—whether IO or CPU—will help in applying the right optimizations and improving overall performance effectively.

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

DEV shines when you're signed in, unlocking a customized experience with features like dark mode!

Okay