
Ivo Anjo

Bryan Antigua

Aaron Kaplan
Over the past three decades, Ruby has assumed a pivotal role in the modern web stack and become a fixture in the tool kits of countless DevOps and platform teams. Today, it is a driving force in contemporary application development, testing, automation, and CI/CD.
For this blog post, we used data from our always-on continuous profiling of more than 3,000 real-world services from hundreds of organizations to track trends in Ruby usage and performance. This data sheds light on important considerations for Ruby development and points to opportunities for performance optimization that many organizations are leaving on the table.
Choice of libraries is key to optimizing Ruby performance
Ruby has a thriving ecosystem of libraries. On average, according to our findings, Ruby applications spend 82% of their CPU time in library code. This means that choosing the right libraries and using them efficiently should be top priorities for optimizing Ruby application performance.
It’s worth emphasizing here that Ruby tends to be relatively compute-intensive. Our data backs up other findings that Ruby applications are generally less I/O-heavy, spending as much or more time on CPU as they do waiting on other services or database requests.

Overall, we found that more than a quarter of all Ruby-driven CPU consumption comes from a small handful of libraries: On average, stdlib accounts for 14.8%, activerecord for 9.8%, and activesupport for 8.1%.

Many of these top contributors to CPU usage lack viable substitutes. However, we found that some of the most widely used Ruby libraries can be replaced by others for substantial performance gains. For example, among database drivers, mysql2 is far more widely used than trilogy—even though it is also far more CPU-intensive.

In other areas, we found that trends in library usage are on the right track. For example:
- pg is the clear favorite PostgreSQL client library for Ruby, as well as the least resource-intensive.
- For JSON serialization, modern versions (2.7.3 and up) of json lead the pack in terms of both popularity and performance, though the also-popular oj is comparably performant.
Elsewhere, library selection has less of an impact on performance. For example, our data shows that web server choice is not a major differentiator for CPU consumption, which is generally comparable among Ruby’s wealth of performant options. (Of course, when assessing the performance of web servers, CPU usage is not the only factor to consider: It’s also important to consider metrics like latency, memory usage, and fault tolerance. We’re still collecting data for those metrics and look forward to sharing our findings soon.)

Among Ruby HTTP clients, where usage is highly fragmented, we observed no clear differentiators in terms of overhead. Median CPU consumption was under 0.1% across all popular libraries, including wrapper libraries.

Better performance is often just a Ruby version away
We measured significantly lower library CPU usage for services on Ruby 3 compared to those on Ruby 2—a clear indicator that migrating to the newest version (and enabling YJIT!) may be a major boon to performance.

Ruby 3.5 is expected to bring substantial performance improvements for certain workload types, and we look forward to tracking the impact of these improvements, such as ZJIT, in future editions of this survey. For example, in our profiling of Ruby 3.4.x and below, set ranked among the most CPU-intensive libraries. With Set now implemented as a core class in Ruby 3.5, teams with set-heavy workloads should consider migrating as soon as possible.
In other areas, migrating to newer versions of Ruby may not bring leaps in performance. For example, we were surprised to find that upgrading Ruby versions alone won’t bring down your CPU overhead from garbage collection: Across versions, the average proportion of CPU that Ruby applications spend on garbage collection wavers between 9.4% and 16.3%.

We have a separate blog post all about optimizing Ruby garbage collection.
Takeaways on optimizing Ruby performance
In this post, we’ve outlined the major opportunities for Ruby performance optimization identified through our continuous profiling of thousands of real-world Ruby services. We’ve demonstrated the compute-intensiveness of Ruby apps, emphasized the importance of careful library selection, and shown how the most popular libraries may not always be the most performant. Finally, we’ve shown the potential performance benefits of migrating from Ruby 2 to Ruby 3 and highlighted the promising outlook for Ruby 3.5.
To dive deeper, you can learn more about monitoring Ruby and Datadog Continuous Profiler. And if you’re new to Datadog, you can sign up for a 14-day free trial.





