Mastering Heroku — Issue #4

I recently had a consulting call with Jesse Hanley (creator of Bento) that got me thinking about an approach many of us are guilty of when our apps are struggling: We just turn the knobs up to 11.

Jesse Hanley@jessethanley

If you're using @heroku and have questions about scale, you should hit up @adamlogic.

Just had a really insightful call with him that took me from "I have no idea what I'm doing, app needs more Performance-L dynos lol" to confident to experiment finding a profitable balance.

September 17, 2018
On Heroku, "turning it to 11" translates to blindly adding dynos and increasing dyno size. This approach can work, but it comes with major strings attached:

  • It gets expensive fast.

  • You risk overwhelming your downstream dependencies, such as hitting a connection limit on Postgres (I touched on this last week).

  • You're masking or ignoring underlying root causes of performance issues.

I subscribe to this crazy idea that Heroku is not expensive. When optimially configured, it can be a steal.

Adam McCrea@adamlogic

Yesterday @railsautoscale handled 1.64M requests. I pay ~$100/mo to host it on @heroku. It *can* get expensive, but that's avoidable. Small teams don't need a dev-ops engineer, they just need guidance.https://t.co/fNOKhXva9d https://t.co/AIycHgDghm

August 14, 2018
So how do you optimize your Heroku setup? Here are some tips that got Jesse on the right track:

  • If absolutely consistent performance is a hard requirement, you need performance dynos. The shared architecture of standard dynos means your performance will fluctuate due to factors completely out of your control.

  • Remove the guesswork from choosing the number of dynos. Use Heroku's own autoscaling, HireFire, or Rails Autoscale to automatically scale up and down as needed. Autoscaling should be a hard requirement for a production app.

  • Once you’re autoscaling, there's little reason to use a larger dyno type than necessary. A smaller dyno lets you autoscale at a finer granularity and save a whole lot more cash. This is another reason jumping straight to Perf-L dynos is usually a bad idea.

  • On the other hand, you do need a large enough dyno to run multiple web processes. Heroku's random routing architecture means you’ll stabilize your performance by adding web processes so your app server can intelligently route requests within a dyno. A good rule of thumb is to choose a dyno type with enough memory to run at least three web processes.

  • Do the math to ensure you don’t exceed database connection limits: [connection pool] * [processes] * [max dynos] <— Do this for each process type (web, worker, release, etc).

With that basic setup, you can focus efforts your app itself. Use an APM like New Relic or Scout to measure and diagnose potential bottlenecks. Any improvements there will result in faster response time, less scaling up, and lower Heroku bills.

Happy scaling!
—Adam