Tag Archives: MongoDB

Ruby Tuesday: Scaling Rails

I’ve heard a lot of horror stories regarding Rails development and how it has trouble scaling, my verdict is still out.  I also think code can be written inefficiently in any language (I’m certainly guilty of writing SQL queries that pull in too many records).

I really enjoy developing in Rails.  I think Ruby is a very terse language and Rails is framework that helps developers achieve peak productivity.  So I’m trying an experiment with BizeeBee.  The team has been through 3 iterations.  At the end of each iteration we’ve been focused on cleaning up our code base.

For this iteration our goals are:

  1. Convert obtrusive AJAX queries (RJS) into straight JS, because we’ve experienced how slow RJS can be.
  2. Make the DB agnostic by removing straight SQL calls and instead relying on the ActiveRecord framework, because we don’t want to deal with mySQL vs. Postgres incompatibilities.

I’ve also talked to a couple people in DevOps to get their thoughts on Rails as a framework here are their suggestions:

  1. Think about  scale from the beginning because you’ll need to scale before you know it.  They seem to almost value premature optimization over no optimizations.
  2. Limit the number of joins you’re performing on your database.  This means restrict the foreign key relationships and try to de-normalize your tables early on.
  3. Think about archiving or aggregating historical data.  This will limit full table scans, and give users a richer experience when dealing with data that pertains to the present.  If you need to retrieve older datasets then you’ll need to design around it by messaging users that you’re retrieving older data.

As BizeeBee moves into the fourth iteration, I’ve started to think about how an open beta will result in more users.  David, my back-end developer, and I spend more time thinking about data modeling.  We know which tables we anticipate growing quickly, how we need to address the growth rat, and have started thinking about partitioning schemes to address the growth of data.  Currently our app is hosted on Heroku, which means we don’t have control over our partitioning scheme.  So if we do want to partition we’ll need to host the app ourselves.  But we like the ease of deployment that Heroku offers and how we can closely mirror the staging and production environments without having to configure them ourselves.

While I don’t anticipate us growing overnight, I think its good to start thinking about these problems early on.  I’ve also anticipated the need for caching in the short-term and will implement it depending on usage patterns.  As far as using a solution like NoSQL or MongoDB, my main reluctance to embrace it is the need for an ACID database, one that maintains data integrity.  I know a lot of startups have openly welcomed both, but my skepticism originates from the need to have a highly accurate system that cannot tolerate data glitches.  I’m dealing with transactional data that belongs to small business owners, and can’t afford for the service to be unreliable.

I’m curious to hear about everyone else’s experience and architecture regarding scaling in Rails and how their stack has morphed overtime…

Enhanced by Zemanta

Performance: Part II Address Scalability Before Its Too Late

As your product and user base grows you want to ensure that your customers both old and new have a good user experience. You want their experience to improve and not stagnate or diminish over time; scalability is another key element to address to ensure the success of your website. Scalability is defined as the capacity to keep pace with changes and growth.

Maintaining a scalable website requires thinking from a business perspective. You want to understand how rapidly your site is growing, and what the frequency of usage is. These two factors serve as metrics for predicting how to allocate resources. You can also use historical usage as an indicator of how much activity you expect in the future. Press releases and media events increase the user base over the course of a few days or even a week by unexpected amounts. Ideally, the number of users is increasing at steady predictable rate week over week. Depending on the type of site you’re running you can figure out what the peak hours for use are, or if user activity increases during certain seasons of the year. Also, knowing the frequency or peak hours of usage helps to schedule maintenance, new feature release, and cron jobs, which won’t interfere with the user’s experience.

Continuing to think in terms of business, you’re site is operating on a fixed budget, hence the amount of resources you have is directly proportional to your operating costs. Until you receive another round of funding or bring in revenue you have to make due with what you have. Therefore, you must understand the limits of your resources in terms of response time, throughput, and concurrency in order to allocate resources efficiently but still guarantee quality. Load testing* is the best way to predict the limits of each of these.

Now lets switch back to thinking like an software engineer. From a code base perspective, web applications should be tier based. Here is a simple tiered approach:

UI -> Business Logic -> Persisted Object -> DB

You might also have another tiered data model that runs in parallel, which could be used to process or retrieve data that is not in immediate use by the user. Usually a messaging protocol such as JMS or RMI is used as a means of communication between these parallel data model tiers. The benefit of having a tier-based is that you can cache data that doesn’t change frequently across tiers, thereby limiting the number of expensive DB calls made. Moreover, as the number of concurrent users increases securing data across users becomes pivotal. With a tier based approach only certain tiers can manipulate and persist data.

I’m sure we’ve all learned from our intro computer architecture class that CPU bound processes are the fastest and can be parallelized, whereas I/O processes are the bottleneck. In the case of a website, accessing the DB is the slowest I/O process. However, you can speed up access to data by sharding the database. Sharding breaks up a large database into smaller pieces that contains redundant information or a parent db can map data to separate dbs.

The last and priciest technique is having multiple servers. Configuring a load balancer to handle requests and the send them to each server is one way improving throughput and response times for user.

Improving the scalability of your website is a good problem to have, because it means your site is growing! But you don’t want to wait until a server crashes or a db thrashes. A little forethought will continue to grow your user base and keep them coming back for more!

* Future article on load testing.

Enhanced by Zemanta