Building Modern Software in the Cloud is a Balancing Act
For 20 years, the model in IT has been to build layers of abstraction, one on top of the other. We evolved from super servers to commodity servers, then virtual machines to containers, and now all the way to “Serverless” infrastructure. Until very recently, each layer was intended to supersede the others, freeing you from needing to think about the layers underneath. But, that freedom was often limiting. Sometimes, abstraction masks the best solution.
Cloud providers have continued to expand their offerings, and today you have access to both on-demand high performance bare metal servers as well as serverless options—the extreme edges of the infrastructure landscape. In addition to being available in real-time, with no ongoing commitment, these services are all interoperable. Applications can freely mix serverless, instances and physical hardware, all on-demand and real-time—all over the world.
When coupled with a rich ecosystem of open source libraries and platforms, applications become as much about assembly as creation. In fact, building software has grown into an art of composition. The notion of “configuration as code” has evolved to “configuration instead of code”, causing a paradigm shift in how software is built. Creating infrastructure in parallel with code eliminates the need to make infrastructure decisions in advance, allowing teams to build high quality software more quickly than ever. The ecosystem and platform flexibility have empowered countless small startups to unseat well entrenched incumbents.
Composition is not without challenges, though. Having an infinite menu of choices is often paralyzing, and making the wrong choice can cost a boatload and set you up for failure down the road. In other words, the complexity of building software is higher than ever. Until very recently, our industry had whole companies that were “Java shops” and “.NET shops”. Today, that sounds like madness. Developers are expected to know multiple languages and frameworks, while also understanding the underlying infrastructure.
The result of all of this is a new playbook, one where you do not necessarily need to think and plan before you build, where you can tinker and test before deciding on a design. But, we’re still humans, and freedom must balance with discipline to avoid chaos. Quality requires thoughtfulness, and speed is the enemy of both. Our challenge now is to learn what that balance looks like, understanding how to take risks while also being prepared to walk away, start over, and try again.
As we seek that balance, one of the most important things is to recognize that we need to recalibrate what we need to master in order to build great software. Understanding the nuance and syntax of a particular programming language is far less valuable today than it was a decade ago. However, understanding how a piece of code will ultimately be run—its performance characteristics, its security implications, its deployment model—is crucial. Developers are no longer building just their little cog in the grand machine. Operators are no longer running black boxes that they can afford to not understand. Instead, we are building and running systems that we understand from code through to execution for the first time since the earliest days of computing.