I talk to customers that have hundreds of critical business applications, and frequently the conversation turns to why and how those apps are being modernized. Factors such as risk from turnover of key knowledge workers, risk of hardware and software becoming unsupported, and reduction in capital expenses lead to app modernization efforts. There are many other reasons that won’t be discussed in depth here.
We know apps are being modernized, but what is a modern app, and what are some hidden benefits to engaging in an application modernization effort?
By definition, an application is modern at the moment it is created, and likely for some time after that. While that is a definition, it is not terribly useful for our discussion. Evolution in technologies, tools, programming languages, and platforms all contribute to what constitutes an application. To improve our definition of modern applications, we need to pin down the time frame and define what a modern app looks like in 2019 and 2020.
What is Not a Modern Application
Looking at an absurd example may help shine a light on what is not a modern application. For example, while most mobile apps are ‘modern’, we could design a mobile app that no one would call modern.
Imagine writing a native mobile application that creates and edits spreadsheets, all in memory, and doesn’t share those spreadsheets with any other device. For all practical purposes, it’s a disconnected, non-scalable singleton. Let’s also consider a suboptimal software design life cycle and use no source code control, never develop tools to automate the building and release of new versions of the app, and let’s use very specific features of the phone, like requiring a specific screen resolution that only exists on one type of phone.
This practice is not terribly resilient. If the phone or app dies for any reason, you lose all of your work. Lose the app installation package and there’s no way to downgrade to a prior release; not only would you lose your spreadsheets, but the code isn’t even around to build the prior release.
We could definitely run similarly poorly designed apps on Kubernetes, which many think is the definition of ‘modern’ – it runs on Kubernetes. Just running a program in a container on Kubernetes does not make it a modern app. Further, a program running in a VM or on bare metal does not necessarily mean it isn’t modern. Micro-services can run on bare-metal or in VMs, and monoliths can run in containers on Kubernetes. There are qualities of an application and how that application is built, run, managed, connected and protected that come together to make it modern.
If during the development of an application we manage to ignore one or more of those qualities and leave it out of our final product, we’ve created an application that is less rich in design than what we would consider ‘modern’.
Qualities of Modern Applications
The following definition has been distilled from customer conversations and engagement with groups across VMware:
A Modern App is a resilient, multi-cloud supportive software service comprised of orchestrated releases of virtual machines, containers, and serverless functions.
That is a mouthful, so let’s break it down in the following sections.
Modern apps are composed of several services, which may include calls out to legacy systems that haven’t been modernized. Software services take their definition originally from service oriented architecture, and the more modern variant, microservices. Services tend to follow the UNIX principal of doing one thing, and doing it well. They are self-contained, meaning they can run on their own, and they are called on by consumers depending on access policies.
Precursors to software services are client-server architectures, fat clients, and monoliths. These architectures would never be called modern on their own, but most businesses have some systems that have critical features that must be carried forward, yet may never receive the funding to be modernized.
One possibility is to modify the legacy app into a modern app over time. New features are added as new external services or microservices that will be used side-by-side with existing functionality, while old features are replaced by more external services. If the application is valuable enough and given enough time, the original code will be completely replaced by the new architecture like the ship of Theseus.
All applications must be running to have value, therefore resiliency is a concern, but we set a higher bar for modern applications. All applications are going to fail. Modern applications factor failure into their design by enabling graceful handling of any possible failure mode. One example of such design is a crash only design. The teams that operate the application should consider intentionally causing failures as part of the ongoing app management and protection. For example, some might consider implementing Chaos Monkey and other chaos engineering tooling. The point is to support and enrich resilient design principles and improve staff skill and preparedness.
Mean time between failures, and mean time to recovery of the application are key resiliency measurements. As such, modern apps must have a Service Level Objective, or SLO, that defines what must be measured to know that the service is providing value. Once SLOs are defined, applications must be designed so that maintaining this level is achievable.
Requirements for resiliency mean aspects such as instrumentation and tracing for observability into the running application must be taken into account to measure against the SLO. It may also mean creating a smaller scope for particular software services in the application; if services are responsible for less, we can focus more on getting the important bits of them right.
Having the right tools to manage the application life cycle improves application resilience. Creating solid CI/CD pipelines that automatically build, run, and test applications is a great start to building resilient modern apps. In addition, penetration testing, load testing, API or other input fuzzing, static code analysis, and full stack vulnerability scanning are all tools that should be considered part of the modern app toolkit.
The quest for more resiliency also leads to concepts such as autonomic response to failures into the app, or app platform. Kubernetes, for example, embeds the concept of health checking the application and restarting or scaling services based on measured health.
Modern applications are designed for multi-cloud deployment models. Most of VMware’s customers are running applications in more than one cloud provider. That observation has been backed by a Gartner survey which finds, “of public cloud users, 81% of respondents said they are working with two or more providers.”
One of the benefits of app modernization is that adoption of the underlying technologies force application developers to abstract the app from the underlying hardware and software, improving deployability. Reducing app coupling to infrastructure means the app can be deployed to an increasing number of different environments while remaining operational and reliable. This opens up the possibility to run the application across more than a single cloud instance or provider. In turn, by enabling apps to run in more places, developers are forced create or leverage tools that enable cross-cloud management and governance. Here, improving the app also facilitates improving the abilities of the teams developing and managing the app.
This all feeds the virtuous DevOps cycle of constant improvement. With one effort to modernize the app, risk is reduced regarding concerns around choices of cloud providers, and governance, and team productivity is improved.
Modern applications are easier to deploy, and can improve overall application deployment reliability. Each technology change from bare metal, to VMs, to containers, to serverless has shown an improvement to the deployability of software. Each transition has made software less dependant on the system running the code. Additionally, CI/CD has improved the time it takes for new code to get into production.
Much of this improvement has been facilitated by the DevOps movement. If you haven’t already, spend some time reviewing the 2019 state of DevOps report. Through improvement in people, processes, and technology, modern applications are much easier to deploy and manage.
We know a modern app likely has an older monolith that needs to get deployed along side of the newer code. That means we still need to be prepared for difficult releases of the old code, but over time it will get easier as old code is replaced.
Virtual Machines, Containers, and Serverless Functions
Modern applications don’t care where they are running. It is completely possible to run a modern app on bare metal, (as unikernels, for instance), in a container, or VM when the tooling and process around how the app is built, run, and managed is automated and orchestrated. The common theme between VMs, containers, and serverless functions is that they are all just ways of packaging an application into an environment in which it can run. Each technology has different properties that can be exploited by the app, but it is the design of the app and the tools and processes outside of the app that enable it to become agnostic where it is running.
Some parts of applications may never support running in containers or as functions, but that doesn’t prevent them from being modernized. An example would be a dependance on a unique database that has become unsupported over time, but which is critical to the operation of the app. If that database was created as a traditional app, it may depend on various hardware level requirements, and may never be portable to containers or functions. You may be stuck with this part of the app running in a VM until it is cost effective to replace the database technology. Still, application modernization may take the form of improving the tooling and processes for building, running, and managing the database.
Many choices like this mean enterprises will have a slew of app components that will continue running on older technologies. Yet progress is still being made that reduces overall risk, technical debt, and the cost of the application. By modernizing what can be modernized, developers and operators are forced to stay attuned to changes in tooling and processes, which will improve their handling of the “left-behind” dependencies.
Most VMware customers today have a mix of these technologies in their applications, and that is why we consider them all a part of a modern application. We can’t just ignore that critical piece of the application which runs on a legacy computer system tucked in the corner. It must become part of the modern app, or be replaced by new modern technology.
DevOps and Multi-cloud topics underpin and are weaved throughout many of the concepts behind modernizing applications. Look to the DevOps movement for inspiration in what happens when failure is forced and tested. As teams accept risk, and start addressing it, they improve, as does the bottom line for operating critical apps.
The act of modernizing most traditional business applications will take months to years, and during this time, the application must be providing value, or it would just be shut down. Applications must modernize over time, or they will become too risky or lose too much value to continue operating. By modernizing our application portfolio, we improve the people, processes and technology in our business. Modernization will never be a complete transition to the latest technology, but will rather be composed of an ever improving bundle of technologies used across all application services that reduce risk and improve resiliency in the overall app portfolio.
Holding on to legacy applications with no eye towards modernizing is a sure method to have high risk and low value applications which will have a negative impact on your business. In modernizing, hidden benefits are gained in areas such as improved team skill levels, improved development and operational processes, higher velocity of application value reaching customers, and lower risk of failure.
Tom Scanlan is an architect responsible for researching and applying emerging technologies to business problems. He has been in the technology industry for roughly 20 years, starting in systems and network engineering role. Tom soon found a passion for automating everything, which led him into software engineering, where the bulk of his career has been spent in DevOps type roles.