<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Vital Logs</title>
	<atom:link href="http://vitallogs.medhelp.org/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://vitallogs.medhelp.org/blog</link>
	<description>... for MedHelp</description>
	<pubDate>Tue, 11 May 2010 21:32:02 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>MedHelp seeking superstar developers</title>
		<link>http://vitallogs.medhelp.org/blog/?p=31</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=31#comments</comments>
		<pubDate>Tue, 11 May 2010 21:31:58 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=31</guid>
		<description><![CDATA[Are you looking for a challenge?  Work on cutting edge technologies for one of the hottest start-ups in tech?  Are you passionate about technology and ready to make an impact?  If so, MedHelp is the place for you!
MedHelp is the world&#8217;s largest online heath community with over 10 million users and growing.  We have been [...]]]></description>
			<content:encoded><![CDATA[<p>Are you looking for a challenge?  Work on cutting edge technologies for one of the hottest start-ups in tech?  Are you passionate about technology and ready to make an impact?  If so, <a href="http://www.medhelp.org" target="_blank">MedHelp</a> is the place for you!</p>
<p>MedHelp is the world&#8217;s largest online heath community with over 10 million users and growing.  We have been featured on CNN, The New York Times, and Business Week.</p>
<p>We strive to build exciting features for our users and drive innovation in the health industry.  We are a health social network where we connect people, help you find the info you need, and discover health applications and tools.</p>
<p>We are looking for top notch engineers.  We are located in San Francisco.  We offer competitive salary, full benefits, and stock options&#8230;and cool co-workers, a pool table, and fully stocked fridge <span class="moz-smiley-s1"><span> <img src='http://vitallogs.medhelp.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></span></p>
<p>Some of our recent projects include:</p>
<ul>
<li>building an <a href="http://www.medhelp.org/user_trackers/gallery/sleep" target="_blank">application platform for tracking and charting medical information</a></li>
<li>implementing real-time activity feeds that scale to handle millions of user activities</li>
<li>developing <a href="http://www.medhelp.org/forums/apps/152?user_app_type=MyPregnancy" target="_blank">interactive health applications to manage and track conditions</a></li>
<li>Mobile apps to manage your health: <a href="http://www.medhelp.org/landing_pages/show/29">My Cycles IPhone App</a></li>
</ul>
<p><strong>Responsibilities</strong></p>
<p>MedHelp is a fast-paced startup looking for motivated and passionate developers.  We look for candidates who are ready to take on a problem and drive it end to end from concept to completion.</p>
<p><strong>Desired Skills</strong></p>
<ul>
<li>Ruby on Rails or related MVC framework development experience</li>
<li>Database experience (MySQL, NoSQL)</li>
<li>AJAX, JS, prototype, CSS</li>
<li>Experience building scalable and performant applications</li>
</ul>
<p><strong class="moz-txt-star">Send your resume to <a href="mailto:jobs@medhelp.org">jobs@medhelp.org</a></strong></p>
<p><a class="moz-txt-link-freetext" href="http://www.medhelp.org/"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=31</wfw:commentRss>
		</item>
		<item>
		<title>Business Analyst/Web Analyst Job Opening</title>
		<link>http://vitallogs.medhelp.org/blog/?p=32</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=32#comments</comments>
		<pubDate>Mon, 15 Mar 2010 05:57:35 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=32</guid>
		<description><![CDATA[LOCATION: San Francisco
DESCRIPTION: MedHelp, with 10 million monthly unique visitors, is the largest online health community connecting people with shared medical interests. Through partnerships with the top health institutions such as the Cleveland Clinic, Johns Hopkins, and Partners Healthcare, MedHelp provides its users with access to quality health information.  MedHelp also is a leading provider [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: 10pt;">LOCATION: San Francisco</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;">DESCRIPTION: MedHelp, with 10 million monthly unique visitors, is the largest online health community connecting people with shared medical interests. Through partnerships with the top health institutions such as the Cleveland Clinic, Johns Hopkins, and Partners Healthcare, MedHelp provides its users with access to quality health information.  MedHelp also is a leading provider of online and mobile health tools with a suite of over 50 condition specific health tools. </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;">CONTACT: Elizabeth Zeiter (elizabeth.zeiter AT medhelp.org)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;"> </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;"> </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;">POSITION:</span> <span style="font-size: 10pt;">Business Analyst/Web Analyst</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;">KEY RESPONSIBILITIES</span></p>
<p class="MsoNormal"><em><span style="text-decoration: underline;"><span style="font-size: 10pt;">Analytics:</span></span></em></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Design reporting and analysis on key traffic metrics, including competitive analysis and comparisons to industry benchmarks. </span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Provide analysis of website traffic including weekly &amp; monthly updates, quarterly and yearly summaries as well as any ad hoc requests.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Provide insight into traffic or behavior impacts from new features, site design changes, current events or other social media influences</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Support Ad Operations/Sales Operations teams in understanding target audience and ad impression availability based on site content, visitor demographic and other strategic opportunities. </span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Derive insights from web behavioral data and click thru analysis to suggest and or create improvements/efficiencies to web site.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Collaborate with team members to develop clear business and measurement objectives for various initiatives.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Stay current with SEO topics and search industry trends.</span></p>
<p class="MsoNormal"><em><span style="text-decoration: underline;"><span style="font-size: 10pt;">Web Tools and Database Use/Management:</span></span></em></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Monitor the collection of data within web analytic tools. Log any inconsistencies/bugs and follow up with technical team/product support.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Assist in set up and maintenance of data capture business requirements, including page tagging recommendations and hierarchy.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Data mine internal database of member data to provide insights about the site experience and web users.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Use hosted and offline tools to synthesize information from a variety of sources and summarize into effective and actionable reports. </span></p>
<p class="MsoListParagraph" style="line-height: normal;"><span style="font-size: 10pt;"> </span></p>
<p class="MsoNoSpacing">KEY DELIVERABLES AND EXPECTATIONS</p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Weekly traffic reports, highlighting any significant changes in traffic trends and/or new feature impacts.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Monthly &amp; Quarterly Excel and/or PowerPoint presentations summarizing data trends, insights, and implications. </span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Ability to collaborate and work well with others in a fast paced environment with multiple objectives and priorities.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Ability to contribute to increasing the level data intelligence and data driven business decisions.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Ability to work effectively independently and as a member of a cross functional team</span></p>
<p class="MsoListParagraph" style="line-height: normal;"><span style="font-size: 10pt;"> </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;">EXPERIENCE REQUIRED:</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Strong analytical skills, highly proficient at analyzing and interpreting data.</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Experience with industry standard web analytics toolsets such as Omniture (preferred), Google Analytics, WebTrends, Coremetrics, etc. </span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Expert user of Excel; SQL experience a plus</span></p>
<p class="MsoListParagraph" style="text-indent: -0.25in; line-height: normal;"><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Some knowledge of marketing segmentation, statistical modeling and experience with multivariate or AB testing</span></p>
<p><span style="font-size: 10pt; font-family: Symbol;">·</span><span style="font-size: 7pt; font-family: "> </span><span style="font-size: 10pt;">Knowledge of SEO and SEM a plus</span></p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=32</wfw:commentRss>
		</item>
		<item>
		<title>Hints on the nginx fair load balancer</title>
		<link>http://vitallogs.medhelp.org/blog/?p=30</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=30#comments</comments>
		<pubDate>Fri, 11 Sep 2009 18:51:39 +0000</pubDate>
		<dc:creator>lray</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[64 bit]]></category>

		<category><![CDATA[bug]]></category>

		<category><![CDATA[fair]]></category>

		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=30</guid>
		<description><![CDATA[The default load balancing for nginx is simple round robin. If you are proxying to a set of peers, and one request for whatever reason is very slow, nginx will continue to give the busy peer additional requests. The result is that requests that might ordinarily be quickly fulfilled will stack up behind the slow [...]]]></description>
			<content:encoded><![CDATA[<p>The default load balancing for nginx is simple round robin. If you are proxying to a set of peers, and one request for whatever reason is very slow, nginx will continue to give the busy peer additional requests. The result is that requests that might ordinarily be quickly fulfilled will stack up behind the slow request.</p>
<p>There is an add on module for nginx called the fair load balancer. There isn&#8217;t all that much documentation available. Hopefully this post will fulfil some of that need. This is of necessity a summary &#8212; the fair load balancer has three weight modes and two scan modes, and can fit a large number of site requirements.</p>
<p>The fair load balancer is initialized in the upstream declaration:</p>
<p><code><br />
upstream mongrel {<br />
fair;<br />
192.168.1.77:4000;<br />
192.168.1.77:4001;<br />
192.168.1.77:4002;<br />
}<br />
</code></p>
<p>This declaration will use fair in its default mode. In this mode, fair will assign idle peers requests first, when all are busy it will assign the requests using a score that depends on both the number of requests assigned to the peer (as most important) and if all equal, to the peer that had the earliest assignment.</p>
<p>Peers may be assigned weights. A weight is an integer value that is related to the number of requests that can be assigned to each peer, although the interpretation is a little different for each weight mode,</p>
<p>Fair also keeps track of peer failures. A failure is defined as an I/O error connecting to the peer &#8212; but not an html error and, most importantly, not a timeout. If a peer fails once, the load balancer will only consider the peer for a request if all others are busy. Moreover, when a peer reaches &#8220;max_fails&#8221;, the software will not assign it a request for fail_timeout seconds.</p>
<p>Here is an example of a configuration that takes advantage of these features. It uses weight_mode=peak to prevent upstream overload, It sets peer failure to pause 60 seconds in assignment on the event of a backend error.</p>
<p><code><br />
upstream mongrel {<br />
fair weight_mode=peak;<br />
192.168.1.77:4000 max_fails=1 fail_timeout=60 weight=6;<br />
192.168.1.78:4000 max_fails=1 fail_timeout=60 weight=6;<br />
192.168.1.79:4000 max_fails=1 fail_timeout=60 weight=6;<br />
}<br />
</code></p>
<p>The weight_mode=peak option imposes a limit on each peer of weight requests, in this case, 6. If all peers have 6 requests, then the directive instructs the load balancer to return busy (nginx will display the &#8220;site is temporarily unavailable&#8221; page). Obviously, this sort of configuration only makes sense if you have a large number of servers and would rather have an error page than an overloaded backend.</p>
<p><strong>Bug:</strong> There is an important bug in the fair load balancer that affects 64 bit systems. ngx_http_upstream_choose_fair_peer_busy has an initialization that is incorrect. The problem line that reads:</p>
<p><code><br />
ngx_uint_t                          best_sched_score = ~0U;<br />
</code></p>
<p>This only assigns a 64 bit integer 32 bits of 1s, it needs to be 64 bits of ones.</p>
<p><code><br />
ngx_uint_t                          best_sched_score = ULONG_MAX;<br />
</code></p>
<p>Is one simple way to fix the problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=30</wfw:commentRss>
		</item>
		<item>
		<title>Memcache and database are out of sync</title>
		<link>http://vitallogs.medhelp.org/blog/?p=29</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=29#comments</comments>
		<pubDate>Wed, 20 May 2009 08:30:35 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[after_commit]]></category>

		<category><![CDATA[innodb]]></category>

		<category><![CDATA[memcache]]></category>

		<category><![CDATA[memcached]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[transaction]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=29</guid>
		<description><![CDATA[We heavily use caching in our models using cache_fu.  However, we started to notice that a small number of objects in our system were out of sync between MySQL and memcached.
In one case, this led to model validation exceptions as a user appeared unregistered in memcache, but when we went to register the the user [...]]]></description>
			<content:encoded><![CDATA[<p>We heavily use caching in our models using cache_fu.  However, we started to notice that a small number of objects in our system were out of sync between MySQL and memcached.<br />
In one case, this led to model validation exceptions as a user appeared unregistered in memcache, but when we went to register the the user the db would complain that the user is already registered.<br />
<strong><br />
What was the bug?</strong></p>
<p>Lets look at the log file&#8230;</p>
<p>Ex) user.save!<br />
<code>BEGIN<br />
Update (0.7ms) UPDATE `users` SET `token` = '665456562', `updated_at` = '2009-05-13 17:22:26' WHERE `id` = 4<br />
MemCache Delete (0.000285)  users:2<br />
COMMIT</code></p>
<p>Uh oh!<br />
We use InnoDB in MySQL to get transaction support and the way rails implements ActiveRecord calls is that it wraps a transaction around everything within an ActiveRecord method call.  This includes the after_save callback to expire_cache.</p>
<p>This leads to the following scenario with two threads where one is reading and another writing:</p>
<p><code>t1: BEGIN t1<br />
t1: update user in db<br />
t1: expire user in memcache<br />
t2: get user from memcache<br />
t2: cache miss -&gt; get user from db<br />
t2: set user in memcache<br />
t1: COMMIT</code></p>
<p>Since t2 is reading from the database before t1 has committed it will read the old value and save the old value into memcache.  The db is updating, but memcache is out of sync.</p>
<p><strong>What&#8217;s the solution?</strong><br />
We need a way for the expire_cache calls after save to be outside the transaction.  This way, t2&#8217;s read will either be before the db update and cache expiry or after the db update on the expired cache.  The three possible cases are listed below.  In each case, memcache and the database remain in sync.</p>
<p>Case 1: t2 is before the COMMIT<br />
<code>t1: BEGIN t1<br />
t1: update user in db<br />
t2: get user from memcache<br />
t1: COMMIT<br />
t1: expire user in memcache<br />
</code></p>
<p>Case 2: t2 is after the COMMIT, but before cache expiry<br />
<code>t1: BEGIN t1<br />
t1: update user in db<br />
t1: COMMIT<br />
t2: get user from memcache<br />
t1: expire user in memcache<br />
</code></p>
<p>Case 3: t2 is after the COMMIT and cache expiry<br />
<code>t1: BEGIN t1<br />
t1: update user in db<br />
t1: COMMIT<br />
t1: expire user in memcache<br />
t2: get user from memcache<br />
t2: cache miss -&gt; get user from db<br />
t2: set user in memcache (new user)<br />
</code></p>
<p>Luckily, there is a great plug-in called <a href="http://github.com/GUI/after_commit/tree/master">after_commit</a> that does what we need.  This plugin implements additional callbacks like &#8220;after_commit&#8221; which run after save, but are outside the commit.</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=29</wfw:commentRss>
		</item>
		<item>
		<title>Kawaii - an amazing web console</title>
		<link>http://vitallogs.medhelp.org/blog/?p=28</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=28#comments</comments>
		<pubDate>Sat, 04 Oct 2008 01:53:18 +0000</pubDate>
		<dc:creator>khassounah</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=28</guid>
		<description><![CDATA[The Ruby on Rails console is one of the most useful tools a web developer could have. It is the backend equivalent of firebug for those not familiar with Ruby on Rails. But every now and then I find myself hoping that I could actually connect to a running instance of ruby on rails and [...]]]></description>
			<content:encoded><![CDATA[<p>The Ruby on Rails console is one of the most useful tools a web developer could have. It is the backend equivalent of firebug for those not familiar with Ruby on Rails. But every now and then I find myself hoping that I could actually connect to a running instance of ruby on rails and debug it.</p>
<p>Today, I decided that I am desperate enough that I was going to look for one (not enough to build one yet). I googled &#8220;ruby on rails web console&#8221; and there it was on the first page: <a href="http://code.google.com/p/kawaii/">KAWAII</a> (which means &#8220;cute&#8221; in japanese).</p>
<p>I had to do some changes to make it work with the tree where I need it, since the tree is on rails 1.2.6. Here is a list of changes if you happen to need it:</p>
<ul>
<li style="text-align: left;"> Modify all html.erb files back to the rhtml extension</li>
<li>Download the prototype 1.6 javascript file and replace the &#8220;javascript_include_tag :defaults&#8221; with an explicit link to the new prototype file (rails 1.2.6 includes prototype 1.5)</li>
<li>Copy the contents of config/initializer/kawaii.rb into config/environments/development.rb</li>
</ul>
<p>enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=28</wfw:commentRss>
		</item>
		<item>
		<title>Ruby Meetup at MedHelp</title>
		<link>http://vitallogs.medhelp.org/blog/?p=25</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=25#comments</comments>
		<pubDate>Mon, 09 Jun 2008 22:09:53 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vitallogs.medhelp.org/blog/?p=25</guid>
		<description><![CDATA[In Feb, we hosted the SF Ruby Meetup.
We had a great time hosting this event and meeting other local developers building apps on ruby.  We are big time rails proponents and we gave a presentation covering our top lessons learned in scaling MedHelp





]]></description>
			<content:encoded><![CDATA[<p>In Feb, we hosted the <a href="http://ruby.meetup.com/6/">SF Ruby Meetup.</a></p>
<p>We had a great time hosting this event and meeting other local developers building apps on ruby.  We are big time rails proponents and we gave a presentation covering our top lessons learned in scaling MedHelp</p>

<a href='http://vitallogs.medhelp.org/blog/?attachment_id=22' title='Ruby Meetup at MedHelp'><img src="http://vitallogs.medhelp.org/blog/wp-content/uploads/2008/06/img_0620-150x150.jpg" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://vitallogs.medhelp.org/blog/?attachment_id=23' title='Ruby Meetup at MedHelp'><img src="http://vitallogs.medhelp.org/blog/wp-content/uploads/2008/06/img_0612-150x150.jpg" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://vitallogs.medhelp.org/blog/?attachment_id=24' title='Ruby Meetup at MedHelp'><img src="http://vitallogs.medhelp.org/blog/wp-content/uploads/2008/06/img_0621-150x150.jpg" width="150" height="150" class="attachment-thumbnail" alt="" /></a>

]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=25</wfw:commentRss>
		</item>
		<item>
		<title>Ruby on Rails: A look back</title>
		<link>http://vitallogs.medhelp.org/blog/?p=21</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=21#comments</comments>
		<pubDate>Fri, 30 May 2008 08:29:56 +0000</pubDate>
		<dc:creator>khassounah</dc:creator>
		
		<category><![CDATA[architecture]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[scaling]]></category>

		<guid isPermaLink="false">http://search.medhelp.org/devblog/?p=21</guid>
		<description><![CDATA[It has been a little over a year since we started rewriting MedHelp&#8217;s software and had to answer a very simple question: which platform should we use?
After much exploration and deliberation, I decided that Ruby on Rails was the way to go. At that time, the debate on whether RoR was scalable or mature enough [...]]]></description>
			<content:encoded><![CDATA[<p>It has been a little over a year since we started rewriting <a href="http://www.medhelp.org" target="_blank">MedHelp</a>&#8217;s software and had to answer a very simple question: which platform should we use?</p>
<p>After much exploration and deliberation, I decided that Ruby on Rails was the way to go. At that time, the debate on whether RoR was scalable or mature enough was raging (and still is), with few high profile stories adding to the drama (a twitter dev <a href="http://www.radicalbehavior.com/5-question-interview-with-twitter-developer-alex-payne/" target="_blank">dissing RoR</a> for what seemed to be architecture failures was a classic).</p>
<p>Just like anyone making an investment decision, I followed the various blogs talking about why RoR is such a terrible platform, why it couldn&#8217;t scale and how it is obviously a bad choice, starting with twitter of course and going through to the various people for and against.</p>
<p>To my surprise (or not) the issues people faced as they scaled RoR were not specific to RoR. In fact they were issues I saw people dabble with for years. Bottlenecked (and sometimes not truly stateless) app servers, expensive database queries, single points of failure, centralized databases.</p>
<p>For some reason many people in the debate assumed that there are platforms that scale and others that don&#8217;t. And that by picking the right platform you will be able to serve millions of users. Unfortunately, it is never that simple. Scaling is a continuous exercise of understanding the bottlenecks in your system and the limitations of your architecture and finding ways to gracefully get beyond them.</p>
<p>Another argument against Ruby on Rails was that Ruby is a slow language or that it consumed too much memory. But wasn&#8217;t this the argument against Java when the world was dominated by C++ fanatics? Wait, wasn&#8217;t this also the argument against C when Assembly developers were the coolest kids on the block? What about machine code.. you get the picture!</p>
<p>The answer to this argument is two folds. The first is an economic one. Developers are way more expensive than hardware. This statement held true for years, and is truer every minute than the minute before. The other part of the answer is that today&#8217;s architecture (thanks to the 90&#8217;s) puts completely stateless software at the heart of your system allowing you to scale horizontally. So it is not really that important how fast each machine is (as long as it is not noticeable to the end user), you can always add another piece of hardware and double your capacity.</p>
<p>So not finding any challenges with RoR that I didn&#8217;t expect to face with any other platform, and having been sold on its design philosophy (long live conventions), the elegance of its architecture and the elasticity of the Ruby language, I decided that MedHelp is going to be a Ruby on Rails shop.</p>
<p>Fast forward one year later. And you will notice that MedHelp is up and running. We were able to rewrite the entire application in RoR in about four weeks. We transformed the site from a simple forum application to a vibrant community.  Added tons of feature, some of which are complex Ajax applications such as <a href="http://www.medhelp.org/user_trackers/show/1" target="_blank">trackers</a>. Swapped out the site&#8217;s interface in favor of better flow and aesthetics. And we did all that while growing our visitors from 2 million unique visitors to 5.5 million uniques.</p>
<p>Our average team size during this year was 3.5 people (we are 6 now). And while all of them are experienced engineers with a lot of experience in building and scaling server software (whom I knew or worked with prior to MedHelp, and am proud to continue doing so today) all of them learned Ruby on Rails on the job.</p>
<p>After all this, I am now taking a deep breath and asking myself again. Have I made the right choice? The answer for me is clearly yes.</p>
<p>The ride was not an easy one. And we had our share of emergencies, head scratching and nervous moments. But none of the mistakes made or the bugs found were caused by Ruby on Rails except in the sense that the platform&#8217;s flexibility made it easy to make some mistakes. But the mistakes were ours. When made, they often showed a misunderstanding of how a certain feature worked, a flaw in our database schema or how our components are distributed across our servers.</p>
<p>Now that we&#8217;ve gone through those pains to grow the site, I think I am ready to share many of the things that we learned or had to re-learn as we grew MedHelp. Each week or two I will share one of the big pitfalls that we managed to fall into, and what lessons we learned as we climbed out of it and started marching for the next pitfall.</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=21</wfw:commentRss>
		</item>
		<item>
		<title>ActiveRecord and includes maxing my ethernet</title>
		<link>http://vitallogs.medhelp.org/blog/?p=19</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=19#comments</comments>
		<pubDate>Wed, 06 Feb 2008 00:01:07 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://search.medhelp.org/devblog/?p=19</guid>
		<description><![CDATA[We recently ran into an issue where using multiple includes were making a huge join on the backend and returning 1000s of rows which was taking all the bandwidth between servers.
Now, as we start to aggressively cache computed data we may run into a similar problem.  For example, we cache some html pages in [...]]]></description>
			<content:encoded><![CDATA[<p>We recently ran into an issue where using multiple includes were making a huge join on the backend and returning 1000s of rows which was taking all the bandwidth between servers.</p>
<p>Now, as we start to aggressively cache computed data we may run into a similar problem.  For example, we cache some html pages in the db that change rarely.  These pages can be huge.  We would not want to return 10s of MBs of data per view of a list of pages (ie, table of contents or index)</p>
<p>The solution is that ActiveRecord has a :select option which does what SQL SELECT does.  We should consider using this when the amount of data returned is very large.</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=19</wfw:commentRss>
		</item>
		<item>
		<title>Caching Lessons Learned</title>
		<link>http://vitallogs.medhelp.org/blog/?p=17</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=17#comments</comments>
		<pubDate>Tue, 22 Jan 2008 08:10:17 +0000</pubDate>
		<dc:creator>avaria</dc:creator>
		
		<category><![CDATA[coding]]></category>

		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://search.medhelp.org/devblog/?p=17</guid>
		<description><![CDATA[We have a set of bugs with caching:
Versioning:

We must version whenever we cache so that we when upgrade, the app uses the updated revision of the cached object
In acts_as_cached, there is a version.  However, in page caching and fragment caching there is no version number.
In page caching, the cached page is saved on disk. [...]]]></description>
			<content:encoded><![CDATA[<p>We have a set of bugs with caching:</p>
<p>Versioning:</p>
<ul>
<li>We must version whenever we cache so that we when upgrade, the app uses the updated revision of the cached object</li>
<li>In acts_as_cached, there is a version.  However, in page caching and fragment caching there is no version number.</li>
<li>In page caching, the cached page is saved on disk.  Our deployment method overwrites the directory which will refresh this cache.</li>
<li>In this case, we should use the same workaround we use in css, icon, and js includes where we define the key as name?&lt;version_number&gt;</li>
</ul>
<p>Includes:</p>
<ul>
<li>Early on, we used :include in acts_as_cached so that we minimize the number of database calls.  However, by over including you can accidentally max out your network.  The include is implemented as a big join so if you have m includes where one column has a large amount of data, you will transfer n^m data.</li>
<li>We have seen this where we had a column that returns results in the order of 10K, but instead of transfering 60 rows of 10K (600K), we were transferring 10^6 * 10K  rows (100MB).  Now, that&#8217;s a huge difference!</li>
</ul>
<p>Expiry:</p>
<ul>
<li> We use fragment caching to save rendering in our views.  However, the base implementation from rails does not support expiry.</li>
<li>Thus, we need to either explicitly expire or use another technique to expire like TTL expire or sweepers</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=17</wfw:commentRss>
		</item>
		<item>
		<title>Server down 12/28</title>
		<link>http://vitallogs.medhelp.org/blog/?p=16</link>
		<comments>http://vitallogs.medhelp.org/blog/?p=16#comments</comments>
		<pubDate>Sat, 29 Dec 2007 03:18:36 +0000</pubDate>
		<dc:creator>khassounah</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://search.medhelp.org/devblog/?p=16</guid>
		<description><![CDATA[Santa Clause&#8217;s gift to us this Christmas was four hours of down time. The issue was caused by a deletion of all stale notifications in the queued_notifications table. The table had a little bit over 3 million records, all of which were stale and needed to be deleted (they were occupying more than 25% of [...]]]></description>
			<content:encoded><![CDATA[<p>Santa Clause&#8217;s gift to us this Christmas was four hours of down time. The issue was caused by a deletion of all stale notifications in the queued_notifications table. The table had a little bit over 3 million records, all of which were stale and needed to be deleted (they were occupying more than 25% of the sql db footprint or about 0.5GB).</p>
<p>Following is the sequence of events for the record:</p>
<ul>
<li>At around 4am I kicked off a delete on all records in that table and went to bed.</li>
<li>The deletion finished about 3 hours later (the mysql client process exited successfully after finishing the delete)</li>
<li>at around 8:48am John managed to get a hold of me to tell me that the server was down.At that stage here&#8217;s what was happening:
<ul>
<li>mysql was taking an unusual amount of CPU (40-50%)</li>
<li>simple queries were taking many seconds to finish sometimes tens of seconds</li>
</ul>
</li>
<li>I  put up the maintenance screen to bring the database back to idle state, but the database still used 10% of CPU on average and show 70-80% of CPU was in iowait state. This is highly unusual especially that the database was not being used at this point.</li>
<li>I also noticed something. While querying for count(*) on queued_notifications resulted about 39k records, show table status showed the original number of records before the delete was started (above 3 million records). This led me to believe that the database was still re-arranging data based on the large delete (not sure what that means yet, but will be investigating further later)</li>
<li>I dropped the queued_notifications table and recreated it with its index and the database started behaving.</li>
<li>Brought all the app servers back online and all seemed to work fine.</li>
</ul>
<p>What should we learn from this:</p>
<ul>
<li>We should avoid large data creation/deletion</li>
<li>We should insure tables that hold transient data get cleaned periodically (currently notifications and feeds)</li>
<li>A slave DB would have avoided us a lot of downtime in a case like this.</li>
</ul>
<p>Sigh!</p>
]]></content:encoded>
			<wfw:commentRss>http://vitallogs.medhelp.org/blog/?feed=rss2&amp;p=16</wfw:commentRss>
		</item>
	</channel>
</rss>

