I’ve been working on a project for a client, and one of their requirements was to host the application on Amazon Web Services, using Elastic Beanstalk (EB). Since I’m always interested in learning new things, I jumped at the opportunity. Now, looking back, I feel like I have a good grasp of EB, and I have to give it an unfortunate thumbs down. It can be better than setting up your own environment from scratch, but I still prefer Heroku for simplicity or Chef for customizability.
Always a Little Behind
One of the first things you’ll find with EB is that the versions are always a little behind. When I fired up an instance in March 2014, the latest Ruby version I could use was 1.9.3, despite Ruby 2.0 being released a year earlier. Since then they’ve added support for 2.0, but it has to be exactly 2.0.0. When we tried to deploy with our Gemfile saying 2.1.2, we got an error. With Heroku, it automatically adjusts the environment to match your Gemfile. It’s a little thing, but having to downgrade your Ruby version just to match what EB provides is irritating. It was especially galling on this project as I actually wanted to use named parameters from Ruby 2.0, but had to skip it to be 1.9.3 compliant.
To make matters worse, upgrading is pretty much impossible. That 1.9.3 environment I spun up in March? As far as I can tell, there’s no way to easily upgrade to the now available 2.0. Instead, I would have to terminate my existing environment and recreate it. Considering that I have an RDS instance tied to it that I would need to dump and restore, I just decided it wasn’t worth it. Again, with Heroku, just edit your Gemfile to change the ruby version, and bingo…done.
Github gems? Forget it.
Bundler has support for installing gems from a git repo, and even adds a handy shorthand specifically for github. Forget using that with EB. Gems via git or github are a strict no-no. You’ll need to vendor the gem source in your app and set up a config file with some confusing values in there. Oh, and also enjoy some generous finger wagging:
In short, if there is an official RubyGem release of the library in question, you should use that version instead; and if not, you should suggest to the library author that an official RubyGem release be made available.
Yeah…I would have used the gem if it were available, but it’s not. And I need to deploy today, not when the gem author finally gets around to publishing a new version, so building from github on master is pretty much my best option. If only EB had a good way to support that…like Heroku does.
EB does support extra configuration for your environment, like installing extra packages or rubygems, or writing extra configuration files. Unfortunately, it’s like a lobotomized version of Chef, and I found it cumbersome and clunky. For example, with Chef, I’ll often use the environment name when writing out config files. In staging? Then I want the Redis keys to be prefixed with “staging”, or I want to enable a different level of logging. With Chef, this is often done by using ERB templates and simple conditionals. With EB, I couldn’t find a way to use templating for the configuration files. It’s all-or-nothing and the same config file is written to every environment. Further, the config files themselves are stored as weird YAML constructs or you have to point to an existing file on S3. It’s hard to explain, but regardless, it’s clunky and much worse than the ERB templates I’ve gotten used to with Chef. Is Chef perfect? By all means, no. But, if forced to do some custom configuration to an environment, I’d choose Chef over EB any day of the week.
If there’s one primary advantage that EB has over Heroku, it’s cost. I don’t have the exact figures, but Heroku can get pricey very quickly. A minimum of $50/mo for the database, plus another $20-30 for dynos, $20 for SSL, then even more for any addons. And this is for a pretty basic application. EB gets you very close to the raw EC2 and RDS costs. With reserve instance pricing, you can slice your costs down to the bone, easily getting in at under $75/mo. However, if you factor in your setup time and general frustration at dealing with a clunky system, the cost argument becomes foggier, especially if someone else is paying for your time to do it. Someone might spend $500 on having you futz with EB, when that money would have paid for a year’s worth of the difference with Heroku. After that year, Heroku might not be a good fit anymore, but I’m pretty sure the EB would not be as well. The difficulty with custom configuration makes me think that any large-scale production app will eventually have to move off EB in order to support some kind of wackiness that EB can’t handle. That’s just the way of these things.
It seems to me that EB exists as a poor reflection of Heroku, mixed with some rudimentary Chef, resulting in a sub-par version of both. For a brand new project, Heroku will get you launched to production faster. For an existing project ready to scale in a cost-conscious manner, a custom Chef setup will allow you to get raw EC2 nodes customized exactly how you want for the lowest possible price. At both ends of that product lifetime spectrum, there are better options than EB.