I was having a fruitful discussion with one of my colleagues – Ruby on Rails developer, Pratik Panchal, regarding absolute inconvenience we had with web frameworks. He told how difficult it was developing PHP web applications lacking debugger, but by the time the applications took the help of Ruby and migrated to the Rails.
On the other hand, I stated it was skeptical how web framework ran on the thread-per-request model. My reasons for disbelieving the framework were application performance and scalability. But to my surprise, Pratik bought an interesting point to my attention that I have not considered earlier – process-shared-sessions.
I am writing this blog – Is ruby on rails application scalable? Because I thought the idea is worth sharing. Rails share database connection between threads and runs as a parallel share nothing process. Multi-threaded execution is a bit difficult in trivial in-memory data. Caching to disk is another problematic thing because of the number of processes attempting to access on-disk data simultaneously. Undoubtedly, there would have been intelligent solutions to solve the problem, but I came across an interesting solution while discussing this problem.
What’s that Let’s dig in!
My solution is associated with one of the hottest topics- JRuby on Rails. JRuby lets you run the application in an integrated environment using the same extent of Java tools, libraries, and process containers. Even the additional project to JRuby enables you to package your Rails application within WAR and host it directly within Glassfish or Tomcat.
Packaging Rails as a WAR is indeed difficult; it wouldn’t go into the deployment of Rails application. To run multiple requests in Rails application simultaneously use an Apache mod_proxy configuration that would proxy requests to server processes. Java web applications are designed to run on multi-threaded, rather than multi-process.
On the other hand, Rails applications are hosted on a separate process that can be extensively modified. JRuby let’s multiple Rails occurrences to be controlled by Rails app WAR. jRuby spawns a new example of the JRuby interpreter for the individual Rails process as all of them are hosted in individual threads within the JVM instance. So instead of configuring a new Mongrel and adding a mod.proxy scale, you Rails application change value in XML file to redeploy.
I found this single-process of shared data as a solution instead of storing shared data within Rails process. So, ensure to use a Java Class to store data, all shared applications should be stored at a lower level with Java process itself. As your application scales and shared data requirements increase the SharedCache class could be modified using Terracotta. The WAR is conveniently clusterable making use of Java application servers like JBoss. This way is not only convenient but enormously scalable without any concern.
Scaling your Rails application is an easy thing; all you are required to do is know your app from scratch about how and when to scale it.
What are the Most Common Problems with Rails App Scaling
You might be familiar that by the time Rails introduces Scalability when your application grows, but the concern is related to the system architecture, not the framework itself. Developing an application using Rails way is not certainly the best approach when your application grows rapidly. I am not even saying that scaling Rails application is always a pain.
Even if you don’t have performance and scalability issues like Twitter, there are still some most common issues when it comes to scaling.
- Poor performance database queries
- Inefficient caching
- Lack of monitoring skills
- Inefficient database engine
- Wrong memory management
- Overall spaghetti code
- Improper background jobs design
- Complicated database schema
- Bad indexing
- app server limitations
- More, and more, and more
Still, Rail is an excellent framework with a huge community and thousands of questions answered online forums. Hundreds of open-source tools are available to build your stack, profiling and analyzing tools to classify bottleneck of your system.
How to Improve the Scalability of Ruby on Rails Application?
- Ensure to use UUIDs in its place of IDs when it comes to using incremental and standard IDs as principle keys as all the database writes have to go through a single database. Using UUIDs can help you spread across many servers in the future.
- Make use of update_all for numbers of updates with the same value or write a custom SQL query. Following the AR method for hundreds of objects is not an ideal practice to go for.
- There are common gems like rack-mini or bullet to detect problems instead of paying some extra memory.
Choose `pluck` instead of `map` to get the exact attributes from multiple objects.
- I would like to bring to your attention is that don’t use ‘length’ – ‘ActiveRecord:: Relation#length’ it will loads up all the mentioned records. Use ‘Size’ for database solution and ‘count’ for better solution of single query.
- Use database-level functions like SUM, SQL, Distinct or Copy. Sum catches the function and returns the result. SQL performs the function and returns the result. Use the function as per your convenience and let me know in the faster comment.
Precisely understand, there isn’t any magic formula of Scaling Rails application as every individual app is unique. Paying attention at the time of development can help you handle its growth. Fortunately, a great set of tools are available to scale your application. However, efficient SQL queries, optimized code, database indexing and some caching good enough for the beginning.
Top Tips to Scale your Rails Application
Tip #1 Cache
It is advisable to use Ajax libraries like jQuery to stream in data to the browser on demand. Make use of reverse/gateway proxy to HTTP responses to use eTags and expiration. Leverage built-in-action, fragment and caching to cache results from your database.
Tip #2 Segregate Data
It is advisable not to store all of your data in the same storage. I have seen so many clients use Hadoop for analyzing a large amounts of unstructured data for scaling the storage. For any further data reporting needs, do your reporting from the main database instead of the production database!
Tip #3 Handle External Dependencies
Check dependencies for ad serving networks or RSS feeds. If the services do not support its hard to grow request load. So ensure to have a fallback strategy.
Tip #4 Unavoidably relational data
At the time of high scaling levels, ensure that MySQL database has to be sharded. Sharding contains datasets into independent. For the customer-oriented Rails applications sharding is based upon userid’s.
So next time when it comes to making technology decision of scaling, instead of asking “does my app scale” listed are the questions you should be asking instead:
- How long would I be able to get away with the Rails application?
- Name the right tool to get the job done for my app?
- Will my app will scale, the assurance you claim to our investors? Never lie to yourself here
- What is more significant: Have your application up and running in-front of real-users or make it scalable for an imaginary future.
Respond to these questions effectively and make an equipped decision. In Conclusion, I would like to bring to your attention what Shopify said years ago at the RoR conference regarding the scalability of the Rails app: “There’s no magic formula to scale rails application. But if the question is, does it scale? The answer is, indeed yes. If you are looking for assistance to scale your existing Rails application, without a doubt, hire Ruby on Rails developer from us to build scalable web architectures.