Your app is slow. It does not spark joy. This post will use memory allocation profiling tools to discover performance hotspots, even when they're coming from inside a library. We will use this technique with a real-world application to identify a piece of optimizable code in Active Record that ultimately leads to a patch with a substantial impact on page speed.

In addition to the talk, I've gone back and written a full technical recap of each section to revisit it any time you want without going through the video.

I make heavy use of theatrics here, including a Japanese voiceover artist, animoji, and some edited clips of Marie Kondo's Netflix TV show. This recording was done...


When API requests are made one-after-the-other they'll quickly hit rate limits and when that happens:

That tweet spawned a discussion that generated a quest to add rate throttling logic to the platform-api gem that Heroku maintains for talking to its API in Ruby.

If the term "rate throttling" is new to you, read Rate limiting, rate throttling, and how they work together

The Heroku API uses Genetic Cell Rate Algorithm (GCRA) as described by...


Ruby 2.7.0 Holiday Release

news , Ruby Engineer

When Heroku launched in 2007 there was only a single Ruby version that could be used on the platform. In 2012 Heroku began to support multiple Ruby versions. Since then, we've had a holiday tradition of releasing the new versions of Ruby on the same day they come out, which always happens on Christmas day (December 25th).

If you're new to the community, you might be curious about where releasing a new minor version on Christmas comes from. To help answer that question, we interviewed Matz's, who works as the Chief Ruby Architect at Heroku in 2015. In his own words:

Ruby was originally my pet project, my side project. So releases usually happened during my holiday time. Now,...


Update: On closer inspection, the lock type was not on the table, but on a tuple. For more information on this locking mechanism see the internal Postgresql tuple locking documentation. Postgres does not have lock promotion as suggested in the debugging section of this post.

I maintain an internal-facing service at Heroku that does metadata processing. It's not real-time, so there's plenty of slack for when things go wrong. Recently I discovered a Postgres performance issue that bogged down the system to the point where no jobs were being executed at all. After hours of debugging, I found that an UPDATE on a single row on a single table was causing the entire table to lock,...


For quite some time we've received reports from our larger customers about a mysterious H13 - Connection closed error showing up for Ruby applications. Curiously it only ever happened around the time they were deploying or scaling their dynos. Even more peculiar, it only happened to relatively high scale applications. We couldn't reproduce the behavior on an example app. This is a story about distributed coordination, the TCP API, and how we debugged and fixed a bug in Puma that only shows up at scale.

Screenshot showing H13 errors

Connection closed

First of all, what even is an H13 error? From our error page documentation:

This error is thrown when a process in your web dyno accepts a connection, but then...


Debugging is an important skill to develop as you work your way up to more complex projects. Seasoned engineers have a sixth sense for squashing bugs and have built up an impressive collection of tools that help them diagnose and fix bugs.

I'm a member of Heroku’s Ruby team and creator of CodeTriage and today we’ll look at the tools that I used on a journey to fix a gnarly bug in Sprockets. Sprockets is an asset packaging system written in Ruby that lies at the heart of Rails’ asset processing pipeline.

At the end of the post, you will know how Sprockets works and how to debug in Ruby.

Unexpected Behavior in Sprockets

Sprockets gives developers a convenient way to compile, minify,...


Rails applications that use ActiveRecord objects in their cache may experience an issue where the entries cannot be invalidated if all of these conditions are true:

  1. They are using Rails 5.2+
  2. They have configured config.active_record.cache_versioning = true
  3. They are using a cache that is not maintained by Rails, such as dalli_store (2.7.8 or prior)

In this post, we discuss the background to a change in the way that cache keys work with Rails, why this change introduced an API incompatibility with 3rd party cache stores, and finally how you can find out if your app is at risk and how to fix it.

Even if you're not at Rails 5.2 yet, you'll likely get there one day. It's...


All previously released versions of Sprockets, the software that powers the Rails asset pipeline, contain a directory traversal vulnerability. This vulnerability has been assigned CVE-2018-3760.

How do I know if I'm affected?

Rails applications are vulnerable if they have this setting enabled in their application:

# config/environments/production.rb config.assets.compile = true # setting to true makes your app vulnerable 

Note: The default value of this setting that ships with Rails in production.rb is false. By default, Rails apps running in production mode are not vulnerable to this exploit.

How do I fix it?

To remediate this vulnerability, applications can either change the...


Rails 5.2 was just released last month with a major new feature: Active Storage. Active Storage provides file uploads and attachments for Active Record models with a variety of backing services (like AWS S3). While libraries like Paperclip exist to do similar work, this is the first time that such a feature has been shipped with Rails. At Heroku, we consider cloud storage a best practice, so we've ensured that it works on our platform. In this post, we'll share how we prepared for the release of Rails 5.2, and how you can deploy an app today using the new Active Storage functionality.

Trust but Verify

At Heroku, trust is our number one value. When we learned that Active Storage...


I recently demonstrated how you can use Rack Mini Profiler to find and fix slow queries. It’s a valuable tool for well-trafficked pages, but sometimes the slowdown is happening on a page you don't visit often, or in a worker task that isn't visible via Rack Mini Profiler. How can you find and fix those slow queries?

Heroku has a feature called expensive queries that can help you out. It shows historical performance data about the queries running on your database: most time consuming, most frequently invoked, slowest execution time, and slowest I/O.

expensive_queries

Recently, I used this feature to identify and address some slow queries for a site I run on Heroku named CodeTriage (the best way to...


N+1 Queries or Memory Problems: Why not Solve Both?

news , Ruby Engineer

This post is going to help save you money if you're running a Rails server. It starts like this: you write an app. Let's say you're building the next hyper-targeted blogging platform for medium length posts. When you login, you see a paginated list of all of the articles you've written. You have a Post model and maybe for to do tags, you have a Tag model, and for comments, you have a Comment model. You write your view so that it renders the posts:

<% @posts.each do |post| %> <%= link_to(post, post.title) %> <%= teaser_for(post) %> <%= "#{post.comments.count} comments" <% end %> <%= pagination(@posts) %> 

See any problems with...


Heroku bumped its Bundler version to 1.13.7 almost a month ago, and since then we've had a large number of support tickets opened, many a variant of the following:

Your Ruby version is <X>, but your Gemfile specified <Y> 

I wanted to talk about why you might get this error while deploying to Heroku, and what you can do about it, along with some bonus features provided by the new Bundler version.

Why?

First off, why are you getting this error? On Heroku in our Ruby Version docs, we mention that you can use a Ruby directive in your Gemfile to specify a version of Ruby. For example if you wanted 2.3.3 then you would need this:

# Gemfile ruby "2.3.3" 

This is still...


Container-Ready Rails 5

news , Ruby Engineer

Rails 5 will be the easiest release ever to get running on Heroku. You can get it going in just five lines:

$ rails new myapp -d postgresql $ cd myapp $ git init . ; git add . ; git commit -m first $ heroku create $ git push heroku master 

These five lines (and a view or two) are all you need to get a Rails 5 app working on Heroku — there are no special gems you need to install, or flags you must toggle. Let's take a peek under the hood, and explore the interfaces baked right into Rails 5 that make it easy to deploy your app on any modern container-based platform.

Production Web Server as the Default

Before Rails 5, the default web server that you get when you run $ rails server is...


Speeding up Sprockets

engineering , Ruby Engineer

The asset pipeline is the slowest part of deploying a Rails app. How slow? On average, it's over 20x slower than installing dependencies via $ bundle install. Why so slow? In this article, we're going to take a look at some of the reasons the asset pipeline is slow and how we were able to get a 12x performance improvement on some apps with Sprockets version 3.3+.

The Rails asset pipeline uses the sprockets library to take your raw assets such as javascript or Sass files and pre-build minified, compressed assets that are ready to be served by a production web service. The process is inherently slow. For example, compiling Sass file to CSS requires reading the file in, which...


Upgrading to Rails 5 Beta - The Hard Way

news , Ruby Engineer

Rails 5 has been brewing for more than a year. To take advantage of new features, and stay on the supported path, you'll need to upgrade. In this post, we'll look at the upgrade process for a production Rails app, codetriage.com. The codebase is open source so you can follow along. Special thanks to Prathamesh for his help with this blog post.

How Stable is the Beta?

In Rails a beta means the API is not yet stable, and features will come and go. A Release Candidate (RC) means no new features; the API is considered stable, and RCs will continue to be released until all reported regressions are resolved.

Should you run your production app on the beta? There is value in getting a...


Patching Rails Performance

engineering , Ruby Engineer

In a recent patch we improved Rails response time by >10%, our largest improvement to date. I'm going to show you how I did it, and introduce you to the tools I used, because.. who doesn’t want fast apps?

In addition to a speed increase, we see a 29% decrease in allocated objects. If you haven't already, you can read or watch more about how temporary allocated objects affect total memory use. Decreasing memory pressure on an app may allow it to be run on a smaller dyno type, or spawn more worker processes to handle more throughput. Let's back up though, how did I find these optimizations in Rails in the first place?

A year ago Heroku added metrics to the application...



Benchmarking Rack Middleware

engineering , Ruby Engineer

Performance is important, and if we can't measure something, we can't make it fast. Recently, I've had my eye on the ActionDispatch::Static middleware in Rails. This middleware gets put at the front of your stack when you set config.serve_static_assets = true in your Rails app. This middleware has to compare every request that comes in to see if it should render a file from the disk or return the request further up the stack. This post is how I was able to benchmark the middleware and give it a crazy speed boost.


A Patch in Time: Securing Ruby

news , Ruby Engineer

There have been thousands of reported security vulnerabilities in 2013 alone, often with language that leaves it unclear if you're affected. Heroku's job is to ensure you can focus on building your functionality, as part of that we take responsibility for the security of your app as much as we're able. On Friday, November 22nd a security vulnerability was disclosed in Ruby (MRI): CVE-2013-4164 . Our team moved quickly to identify the risk to anyone using the Heroku platform and push out a fix.

The vulnerability

The disclosed Ruby vulnerability contains a denial-of-service vector with the possibility of arbitrary code execution as it involves a heap overflow. In a...


Ruby 2.0.0 Now Default on All New Ruby Applications

news , Ruby Engineer

Heroku provides an opinionated platform in order to help you build better applications. We give you a default version of Ruby to get you started, and give you a way to declare your version for total control. In the past creating an application would give you 1.9.2, starting today the default is 2.0.0.

Ruby 2.0.0 is fast, stable, and works out of the box with Rails 4. Applications running on 2.0.0 will have a longer shelf life than 1.9.3, giving you greater erosion resistance.

Default Behavior

If you have a previously deployed app it will continue to use Ruby 1.9.2, any new applications will run on 2.0.0. Heroku is an erosion resistant platform, which means we will not change a major or...


Empowering Change: Programming Literacy for All

news , Ruby Engineer

There has never been a better time to be a programmer. Every day more and more gadgets get connected or over-clocked. Programming is so prevalent that it often goes unnoticed in our daily lives. Whether we're scripting out social presence with IFTTT, or doing taxes with Excel, automation and programming has become an inescapable part of the modern world.

Heroku believes that to invest in our future, we must invest in programming literacy. While we're waiting for recursion to be a staple in our children’s classrooms, we can work on continuing and higher education today.

Heroku engineers are given opportunities and encouragement to be part of this movement. They’ve done so through...


Adding Concurrency to Rails Apps with Unicorn

news , Ruby Engineer

With support for Node.js, Java, Scala and other multi-threaded languages, Heroku allows you to take full advantage of concurrent request processing and get more performance out of each dyno. Ruby should be no exception.

If you are running Ruby on Rails with Thin, or another single-threaded server, you may be seeing bottlenecks in your application. These servers only process one request at a time and can cause unnecessary queuing. Instead, you can improve performance by choosing a concurrent server such as Unicorn which will make your app faster and make better use of your system resources. In this article we will explore how Unicorn works, how it gives you more processing power, and how...


Run JRuby on Heroku Right Now

news , Ruby Engineer

JRuby

Over a year ago Heroku launched the Cedar stack and the ability to run Java on our platform. Java is known as a powerful language - capable of performing at large scale. Much of this potential comes from the JVM that Java runs on. The JVM is the stable, optimized, cross-platform virtual machine that also powers other languages including Scala and Clojure. Starting today you can leverage the power of the JVM in your Ruby applications without learning a new language, by using JRuby on Heroku.

After a beta process with several large production applications, we are pleased to move JRuby support into general availability immediately. One of these companies Travis CI which provides free CI...


Hacking mruby onto Heroku

news , Ruby Engineer

If you're in the Ruby world, you've likely heard about mruby, Matz's latest experimental Ruby implementation. What I bet you didn't know is that you can run mruby on Heroku right now. As a matter of fact you can run just anything on Heroku, as long as it can compile it into a binary on a Linux box.

If you're new to mruby, or to compiling binaries take a look at my last article Try mruby Today. I cover getting mruby up and running on your local machine. If you are already up to speed then follow along as we use vulcan to package mruby as binary, wrap it up in a custom buildpack and then launch an app to use mruby on the Heroku cloud.

Continue Reading ...

Yesterday

If...


Ruby 2.0 Preview Available on Heroku

news , Ruby Engineer

When Heroku first launched you could only use one version of Ruby: 1.8.6. As the Ruby implementation matured and improved, so did Heroku. We recently announced the ability to specify your ruby version on Heroku, and we are happy to announce the first preview-build of Ruby available: starting today you can use Ruby 2.0 preview1 on Heroku.

Ruby 2.0

The Ruby core team has been hard at work on Ruby 2.0, which has a host of new features and boasts performance improvements. You can get a list of the major new features on the official Ruby 2.0.0 Preview1 announcement.

Heroku has been committed to the Ruby project by sponsoring the work of Yukihiro "Matz" Matsumoto, Koichi Sasada and...


Sunsetting the Argent Aspen Stack

news , Ruby Engineer

Heroku's Aspen stack is the product that launched our company and inspired a new class of cloud services. After much deliberation and careful thought, we have decided to sunset the Aspen stack by Thursday, November 22nd. We ask application owners still using Aspen to migrate to Cedar.

Since Aspen's launch over four years ago, Rails has seen the introduction of Bundler for dependency management, the asset pipeline, and a major framework re-write. Heroku has also grown, and with the introduction of the Cedar stack, we have moved beyond our humble origins and have become a true polyglot platform.

The Aspen stack was a prototype that served as a living vision of what a platform that...


Sunsetting and Deprecation at Heroku

news , Ruby Engineer

Software erosion is what happens to your app without your knowledge or consent: it was working at one point, and then doesn't work anymore. When this happens you have to invest energy diagnosing and resolving the problem. Over a year ago Heroku's CTO, Adam Wiggins, first wrote about erosion-resistance on Heroku. Part of erosion-resistance is communication, and knowing what to expect moving into the future. This post will clarify what we mean by erosion-resistance, and help you understand what to expect when one of our features is deprecated or is sunset.

Erosion Resistance

Erosion-resistance means that your apps are protected against accidental or unannounced changes because...


Multiple Ruby Version Support on Heroku

news , Ruby Engineer

Maximizing parity between development and production environments is a best practice for minimizing surprises at deployment time. The version of language VM you're using is no exception. One approach to this is to specify it using the same dependency management tool used to specify the versions of libraries your app uses. Clojure uses this technique with Leinigen, Scala with SBT, and Node.js with NPM. In each case, Heroku reads the dependency file during slug compile and uses the version of the language that you specify.

Today, we're pleased to announce that we've added support for specifying a Ruby version to Gem Bundler, the dependency management tool for Ruby. This will...



Subscribe to the full-text RSS feed for Richard Schneeman.