Why you should avoid virtual machines for development

Why you should avoid virtual machines for development

I've previously written about why you should use virtual machines for development, but there's a flip-side to that coin...why you shouldn't. It comes down to one simple point - resource usage. Virtual machines (VM) are (or at the very least, can be) resource intensive. The reason is simple, the host needs to dedicate resource from what it has to the VM for it to run.

As a developer today, there's a wealth of knowledge out there to draw upon. From StackOverflow to specific documentation for languages and frameworks. All information is easy to access, but browsers have become increasingly memory hungry in pursuit of performance (looking at you, Chrome). By running several virtual machines, alongside a good few browser tabs, and even multiple browsers for web development testing, there will come a time when you will need to start a new machine, and cannot.

An error from Hyper-V stating the virtual machine cannot be started due to insufficient RAM
Unable to start virtual machine - no memory

With most laptops coming with 8 or 16GB RAM as standard, this memory limit is quickly and easily hit. I get it fairly regularly with my work laptop which is a mobile workstation with 32GB RAM.

What's the Alternative?

There are two main alternatives to VMs for development. The obvious one is to run everything locally. If you need MySQL, Redis, MongoDB or anything else which would be otherwise on an external server to your code in production - run it locally.

This will provide one of the fastest environments to work on. With everything running locally and no network ingress or egress to slow down any data or processing. I've seen this in action in a current setup. One setup runs on 5 separate VMs and takes around 35 minutes to run the full test suite. Another has everything locally, and runs the test suite for the application in 6 or 7 minutes.

Another alternative is containers. They are becoming increasingly popular and prevalent, with Docker and Kubernetes are the stand-out leaders in this area. These virtualise some of the infrastructure but, crucially, sit on-top of the Operating System kernel. As such, running them requires fewer system resources to run because they aren't running a full Operating System themselves - only the software required to perform their actions.

This method isn't as as fast as running all services locally, for reasons already given. It is, however faster than running individual virtual machines. In the application mentioned for the benchmarks provided, a setup within GitLab for running the test suite uses Docker for MySQL and Redis. This completes the test suite in around 20 minutes.

Choose your technology carefully

Looking at the two alternatives to virtual machines alone, you'd think the best option is the "run everything locally" option. It offers the developer the best performance, and the most stability. But there's still a trade off to be made.

If you have a simple LAMP stack (Linux, Apache, MySQL/MariaDB, PHP) with everything installed nicely, what happens when you want to upgrade one of them to try it out? MySQL 5.7, as an example, is rapidly coming to the end of its naturally supported life, with MySQL 8 being the latest version. If you want to upgrade to run your software on MySQL 8, great. But whilst you are testing, how do you support the current live version running on 5.7?

If you have a Wordpress site, it still supports PHP 5.6 (because there's enough demand for it - despite being unsupported officially for nearly 2 years). The two versions after 5.6 are unsupported, too. So what if you wanted to upgrade to a supported version of PHP to test things out, whilst maintaining active support and development for your live site?

Both real-world scenarios. One is a lot easier to do than the other (multiple-versions of PHP on the same machine is certainly possible, and regularly done). But there's still complexity involved.

In which case, containers might be better suited. You tell them what needs to be installed, and which versions to install, and you can update, break, fix, destroy, and start all over again. Getting containers up and running shouldn't be too difficult (I've never properly tried), but there is a learning curve involved.

Also consider how things are going to run in production. Is everything on one machine? Will it be on separate machines? Running in containers? That can help drive the decision for you.

If you're going to run containers in production, then develop using containers. It's really the only way to make sure things work.

If you're running everything on a single host, then keep everything as an all-in-one development environment. Though I would look at doing this as either a virtual machine (I know - goes against the title, right? or as a single container with all the services.

Multiple hosts are where things get more interesting. I like to develop on a near replica of the environment the code will be deployed in (I don't really want to mimic a load balanced setup, just a host, external database, external cache etc.) to allow me to test connection failures between services. You can't do this having everything on one box, or in one container.

It's not easy to find the right balance or setup for development. And actually finding it is going to take some time and effort. Not all companies can afford for their developers to spend the time doing it (though arguably, can they afford not to?).

If you have the time, either as part of your day job, or in your spare time, play around with a different way of spinning up your tech stack. You never know, it might make you more productive in the long run.