Resistance to change is literally built into us.

It’s not an exaggeration to say that most of your body’s systems are designed to keep things the same as much as possible.

This process is called homeostasis, and it’s the reason you don’t fall over into a diabetic coma after eating a large meal, or drop dead from hypothermia during winter. Your body is constantly fighting against change, trying to keep things the same.

And why not? Change means extra energy spent dealing with new things. It’s easier to maintain the status quo than it is to deal with those new things.

Our minds are no different. We thrive on routine. We’re insanely productive once we have an established process to accomplish a task.

Adapting to new situations, technologies, or ideas takes effort, and that’s always a tough sell compared to just ignoring it and hoping it’ll go away while we continue to use our existing systems/methods/biases.

Unfortunately, the world is always changing, and the world of technology even more so.

We have to learn to deal with change, while not losing the benefits of establishing systems.

Immutable Infrastructure

This is where Immutable Infrastructure comes in.

I know that seems inconsistent. I was just saying we need to accept change, now I’m saying we should be making things “immutable”, i.e. unchanging.

Immutable infrastructure is the idea that you want individual pieces of your systems to be unchanging. Instead of making manual changes to an existing server, you instead tear down the old one and replace it with a new one that has the updates you wanted.

The idea isn’t to avoid changes to your infrastructure as a whole, it’s to avoid making changes to pieces of it in-place.

It’s adjusting how we make changes rather than avoiding all change whatsoever.

A Whole New World

Peer into the alternate reality crystal ball for a moment, and let’s see what things could be in the world where you adopt immutable infrastructure.

Your most important task for the day is scaling up your app. It’s so awesome it hit the frontpage of Reddit and HackerNews, and your servers are screaming from the increased traffic as everybody and their boss realizes they’ve been missing out on the best thing since Taco Tuesday.

In your amazing foresight, you knew this would happen (your app is, after all, just one step below Taco Tuesday in sheer awesomeness). Past-you decided to bundle your app up into a ready-to-go image that has all the dependencies pre-installed and configured, so it could start serving traffic the instant it boots up.

Scaling up just means logging into your app dashboard and starting up more copies of that image. Your app starts up the instant the new VMs are running, and now everyone on Reddit and HackerNews can throw piles of money at you while using the amazing tool you built.

Benefits

Okay, the hyperbole might have been a bit over the top, but the benefits of immutable infrastructure are real and very much not exaggerated.

Faster Scaling

If you’ve pre-baked your app and all its dependencies into a single image your app can immediately get to work when you start up a new copy.

In comparison, if you’re having to install your app and dependencies on every server after startup, even if that process is automated, your systems are burning money.

Every server you spin up ends up with a significant amount of time before it can be productive. Until you or your scripts get around to it, they’ll just sit there eating into your cloud bill and giving you nothing in return.

This isn’t a minimal amount of time, either. A previous client used AWS Elastic Beanstalk to automate their app deployments and scaling. EB, by design, goes though the entire app-dependencies install process on each VM as they spin up.

As a result, when we added new instances to the environment it would take 8-15 minutes for any particular instance to finally start serving traffic properly.

When your app is getting hammered with traffic and you’re losing money, that’s an eternity.

Autoscaling Enabled

If you have to manually install your app and dependencies on each server, you’re locked into a manual scaling process.

Need more servers? Spin up new ones and have someone provision them with the app and dependencies.

If you have ready-to-go images, though, you can start automatically scaling your app based on the workload it’s receiving.

  • Are the queues getting backlogged? Spin up more worker nodes to help until the queue is back under control.
  • Are the main servers close to maxing out their CPU and memory from a traffic increase? Add more app instances to manage the load, and then get rid of them when traffic drops off again.

Autoscaling is a tremendously powerful tool for dynamically adapting your app’s capabilities to actual workloads.

You need ready-to-go pre-baked images to truly take advantage of that.

Easy Rollback

Sometimes you deploy a bad version of your app and have to do a rollback.

If you were upgrading your code in-place on your app servers, now you have to figure out how to switch that code back to the original version.

I hope you were using version tags and don’t have massive dependency changes. That could easily mean an hour of downtime per server changing things back.

Instead of that mess, immutable infrastructure would mean you can leave your old servers up and running, just not serving traffic, until you’re sure the new deployment is solid.

After all, you spun up completely new servers; nothing says the old ones can’t be kept on standby to make sure things go well.

Since everything is pre-baked, you can even spin up new copies of the old version if you later discover you need to do a rollback, and you’ll be confident that your app is running exactly as it was previously.

Well-Defined Starting Point

Even if you want to control your infrastructure manually (no judgment here), immutable infrastructure can still improve your workflows by letting you create base images that you build on top of.

If you’re always using Rails behind an nginx proxy, there’s no reason to have to install everything each time.

You can have a base image that has all your standard toolchains pre-installed, and so your end-of-line deployment is as simple as uploading the new app code and switching over your traffic to the new instance.

If you have monitoring systems, SSH certificate authentication configurations, or other things you really want to have on every single server, you can pre-bake those into a standard image that you use for everything.

Avoid Third-Party Outages

A subtle but powerful benefit from pre-building your images is that you’re no longer beholden to external dependencies your install process has.

I’ve had package repositories remove libraries I was depending on for arbitrary reasons. That’s their right, but it can play merry havoc when spinning up a new copy of your app.

This gets even worse if you have an outage of a major repository like NPM or PyPI. If one of those goes down and you’re reliant on them for your start-up installs, you’ll be dead in the water until they’re back up.

Build your images once, and then you can spin them up whenever you want to without needing to worry about whether the package repo is available.

Tools

There isn’t much of the usual tool jockeying in the immutable infrastructure space, but that’s because the existing tools are more than sufficient to the task.

Packer

Packer is focused 100% on automating image creation.

As far as I’m concerned, this is the industry standard and you don’t need to look any further if you’re working with virtual machines.

It can make images for all of the major cloud providers, as well as private virtualization platforms like ESXI, Proxmox, or even VirtualBox.

Docker

Docker is the industry standard tool for building container images.

Everything I’ve talked about with immutable infrastructure applies to containers as well as virtual machines.

Containers are their own topic, but I’d be remiss if I didn’t make note of them here.

It’s nearly impossible to avoid containers in modern development. I’d suggest getting comfortable with them sooner rather than later.

Action Steps:

Fire up those fingers, here’s your action steps for incorporating immutable infrastructure into your processes:

  • Use Packer to set up a static website with Apache, nginx, or whatever your favorite webserver is. This will get you familiar with the process of configuring and using Packer without bogging you down in minor details everywhere.
  • It’s a quick jump from a static site to baking an image with your app pre-installed.

Next Up: Final thoughts and your path forward.