Rails isn’t Slow, You Just Don’t Know How to Use it

Shaqqour
4 min readOct 27, 2020
Photo by Mathew Schwartz on Unsplash

Yes, I just said that. Rails could be as fast as any other framework if it is used the right way. Rails has been serving many companies for nearly two decades now. It has been amazing and one of the first choices for startups whether it is used as a full solution (Backend and Frontend) or as an API server for websites and mobile applications.

The reason some people complain of Rails being slow is related to how they access their data. Ruby on Rails is actually an elegant syntax. It is very developer-friendly; you can write code in easily. It is the reason why it was first created.

If you follow my rules below, you don't have to worry about the size of your data, and you will be able to boost the performance of your Rails backend application.

Use plain SQL statements

ActiveRecord was built to make things easier and less complicated. However, try to avoid using it if possible, because its performance drops when dealing with slightly large and raw data. Try to use plain SQL statements which might be a little complicated, but trust me when comparing the speed, it is worth the hassle.

You can read my other blog post How to Use Plain SQL in Rails which explains in detail how to write and run SQL queries inside your backend Rails application.

Don’t query for data that you don’t need

When you want to fetch data from the database, try to be as specific as possible.

For instance, User.where(age: 30)will load all the information about users who are 30 years old. If you are only interested in the first and last names, there is a selectmethod that can help you with that. So instead of querying without any specifications, you could simply do the following:
User.select("first_name", "last_name").where(age: 30)

This makes the run time faster because it pulls less data.

Use find_in_batches or find_each to iterate over records

One of the bad habits that Rails developers tend to do is to use Model.all ActiveRecord method to iterate over objects. This is fine if your application is small, but if your application is dealing with a large amount of records like 500K, it will be a disaster. Your server will definitely crash due to memory over-usage.

You can avoid this by using find_in_batchesmethod, which divides all the records into small batches and iterates over each batch at a time instead of iterating over all the records at once. The default amount of each batch is 1000. However, you can set your own size using the (:batch_size) argument such as in the example below:

Customer.find_in_batches(:batch_size => 100) do |customer|
customers.each do |customer|
customer.country = "United States of America"
end
end

Minimize the number of transactions by using ‘Model.transaction’

Transactions occur any time an object needs to be saved. Another way to make your application run faster is to minimize the number of your transactions by using thetransactionmethod to group your operations. For instance, you could write the previous example in an even more efficient way that instead of submitting changes after every single record, it will submit every 100 records. Here is an illustration of how to do that:

Customer.find_in_batches(:batch_size => 100) do |customers|
Customer.transaction do
customers.each do |customer|
customer.country = "United States of America"
customer.save
end
end
end

Update all records at once

This is a common mistake that many developers fall into by trying to iterate over a whole table to update one single attribute and sometimes only for a few records. Here is a bad practice to update a table:

Customer.where(city: "Belmont").each do |customer|
customer.zipcode = "94002"
customer.save
end

The code above works just fine, but imagine you are iterating over a 500K records table; this will be very expensive because it is updating the table record by record. Here is a better way to approach this kind of update:

Customer.update_all({zipcode: "94002"}, {city: "Belmont"})

Avoid ‘destroy’ if you can

There is a difference between destroy and delete in Rails. delete will only delete the record with no further actions. However, destroy will also go back and delete all related operations about the deleted record such as callbacks. This takes more time; in other words, it’s very costly. Therefore, if you wish only to delete the record, use delete.

Finally, if you follow these rules, I promise you Rails won’t be as different as any other framework. While ActiveRecord is slow when dealing with massive data, you could find a way around that and keep enjoying this beautiful syntax. If you have any other reason you want to share about why Rails is awesome or not, please do so below.

--

--

Shaqqour

Full stack software engineer. Passionate about making people’s lives better and easier through programming. LinkedIn.com/in/shaqqour