Heroku Dyno Sizes
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. ↩
Resources
- https://ec2instances.info/ – helpful for searching AWS instance types based on CPU and memory.