I’ve been exploring a transition from Heroku to AWS ECS, but I’ve had trouble matching Heroku dynos to AWS instance types.

Heroku explicitly defines the memory they provide for each dyno, but CPU allocation is less clear. I think with many apps being memory bound, it’s not that big of an issue, but it makes planning a challenge.

In this post I’ll match Heroku dynos to EC2 instance types and learn a bit about how Heroku schedules dynos along the way.

Heroku jargon

Here is the table Heroku provides to compare instance types. As you can see, there are a few pieces of jargon used to describe instance types. Lets define them.

  • Dyno Type – the name for the dyno (e.g. standard-1x)
  • Memory (RAM) – how much memory your dyno can use until it hits swap (e.g. 0.5GB)
  • CPU Share – an ambiguous term regarding CPU allocation on a shared machine. I’ll expand on this later.
  • Dedicated – related to CPU Share. Indicates if your sharing compute resources with neighbors on a machine.
  • Runtime – how your dyno is organized by Heroku. This is more for private spaces where your dynos run in a VPC on dedicated machines for you.
  • Compute – another ambiguous term about how much CPU you can use. This is relevant for shared machines and I’ll discuss this more later.
  • Dyno units – a currency of sorts that you buy with an enterprise contract at Heroku. The price varies by contract and quantity but they range from ~$45/unit to ~$35/unit.

Dyno types

Here is the same Heroku table provided for reference.

Dyno Type Memory (RAM) CPU Share Dedicated Runtime Compute Dyno units consumed
standard-1x 512 MB 1x no Common Runtime 1x-4x 1
standard-2x 1 GB 2x no Common Runtime 4x-8x 2
performance-m 2.5 GB 100% yes Common Runtime 12x 8
performance-l 14 GB 100% yes Common Runtime 50x 16
private-s 1 GB Burstable yes Standard Private Spaces 2x-10x 5
private-m 2.5 GB 100% yes Standard Private Spaces 14x 10
private-l 14 GB 100% yes Standard Private Spaces 52x 20
shield-s 1 GB Burstable yes Shield Private Spaces 2x-10x 6
shield-m 2.5 GB 100% yes Shield Private Spaces 14x 12
shield-l 14 GB 100% yes Shield Private Spaces 52x 24

The hardware

Heroku is vague about the machines they provide. We know they run on AWS and that they guarantee memory while CPU is variable.

Dyno type Total CPU on instance Memory per dyno CPU Share
standard-1x 8 512MB 1x
standard-2x 8 1GB 2x
performance-m 2 2.5GB 100%
performance-l 8 14GB 100%
private-s 2 1GB Burstable
private-m 2 2.5GB 100%
private-l 8 14GB 100%

Looking at the standard-1x and standard-2x, we see that both instances have the same CPU count. The difference is in the limits. Heroku appears to limit usage using cgroups (i.e. containers). The “CPU Share” and “Compute” are the interesting fields in this case.

“CPU Share” is the differentiator between standard-1x and standard-2x. I believe multiple standard-1x and standard-2x instances are shared on one instance that has 8 CPUs total and 62.91 GB (according to /proc/meminfo).

By looking at /proc/meminfo and /proc/cpuinfo we can find corresponding AWS instances.

For the standard-1x, it appears we’re running on a r3.2xlarge (R3 High-Memory Double Extra Large).

We can see all of the results in the following table.

Matching dyno nodes to AWS instance types

dyno type CPU dyno MEM instance MEM AWS instance Heroku units Heroku cost 1 AWS cost (reserved) 2 Heroku premium
standard-1x 8 0.5 62.91 GB r3.2xlarge 1 $40/mo $2.46/mo 16x
standard-2x 8 1GB 62.91 GB r3.2xlarge 2 $80/mo $4.92/mo 16x
performance-m 2 2.5GB 3.853 GB c3.large 8 $250/mo $53.29/mo 4.5x
performance-l 8 14GB 15.4 GB c3.2xlarge 16 $500/mo $213.16/mo 2.3x
private-s 2 1GB 4.045 GB t2.medium 5 $200/mo $20.95/mo 9.5x
private-m 2 2.5GB 3.853 GB c3.large 10 $400/mo $53.29/mo 7.5x
private-l 8 14GB 15.4 GB c3.2xlarge 20 $800/mo $213.16/mo 3.75x

The performance series dynos are the same as the private series. I haven’t examined the shield dynos in detail, but I believe they are equivalent to the private series dynos.

The private-s, which has no equivalent, is “burstable” because it runs on a t-series dyno, which provides burstable CPU usage for a short time.

With the performance and private dynos, you are actually getting a full AWS instance to your self. For a standard series dyno, you have some share of that underlying AWS instance; your memory is limited, but depending on how active your neighbors are, you can use up to 4 CPUs for 1x and 8 CPUs for 2x (all of the CPUs on the instance).

1 assuming $40/dyno unit

2 normalized for standard1x and standard2x. I’m assuming they schedule the max amount of dynos based on memory, so 62 for standard-2x and 124 for standard-1x. For reference, the reserved cost of r3.2xlarge is $305.14/mo.