This module examines the second transformational path to application modernization which involves taking a new approach to how application code should be architected using microservices and containers. In this module, we will Compare a legacy application architecture with a modern, cloud-native one using microservices. Specifically, we will describe some of the drawbacks of a “monolithic” architecture to the advantages of adopting a “microservice” architecture. Describe a general pattern for modernizing monoliths into microservices. And explore why Containers and Container Orchestration Platforms are essential to modern, cloud-native applications. Lastly, we will bring it all together and show how the “Garage Method” formalizes application transformation and modernization. In this video, we will look at a modern application architecture, its guiding principles, and contrast them to a legacy, monolithic architecture to highlight its benefits. For companies that operate legacy applications, the choice to modernize can be compelling since modernization potentially provides a means to preserve investments while capitalizing on the (dynamic) resources, flexibility, and scalability of the cloud. As we have learned, a cloud native approach includes many aspects, but you only need to remember three guiding development principles that are consistent when creating new or modernizing. The first, of course, is to adopt agile methods. We already learned that adopting Agile methods is central to a Cloud Native approach, which speeds the application development lifecycle and continual integration, delivery, and deployment processes. Before beginning any development to modernize, product delivery teams should decide upon a human-centric, agile framework to manage development (e.g., scrum) integrated with cross-team communication channels, and select which cloud-native tooling and technologies will be used to automate CI/CD cycles and allowing time for education and training. Secondly, DevOps teams should Rely upon Containers as the core application packaging method for maximum agility, flexibility, portability, and scalability. As we touched upon previously in the course, Container technologies abound for use in all lifecycle phases from CI/CD through to staging and production. The Kubernetes orchestration platform is becoming ubiquitous among cloud providers enabling fast, policy-driven scaling and immediate access to multi-cloud environments. Thirdly, follow a microservices architectural approach in which application tasks are broken down into single-function services known as microservices. Loosely coupled microservices that form a cloud-native application can be independently improved and delivered continuously with automation. They can be updated-in-place without downtime and their functions can be reused by other applications. Using these three guiding principles, the path to cloud-native and multi-cloud will naturally be made clear. Next, let’s take a closer look at Monolithic Architecture and then contrast it with Microservice architecture… Many enterprises and organizations have legacy applications that are architected as self-contained, single-tiered monoliths. Monolithic applications are typically designed to help humans accomplish all steps of tasks and workflows for a given system; often attempting to encompass and reflect all human and physical functions of real-world systems such as those found in retail, finance, or transportation. Although initially simple to develop and test, a monolith’s code tends toward tightly coupled functions without clear module boundaries, causing low cohesion, which can lead to many long-term issues. We can visualize this using a warehousing application example that shows its four major workflow functions, which include Inventory, Processing, Shipping, and Receiving. Likely, most monoliths evolved organically, adding new functions as needed without much consideration for reusability or long-term maintainability and eventually becoming more-and-more unmanageable and fragile to operational changes over time. For our warehouse app., this could be a “Finance” function. As the application’s customer base grows, so do expectations for new features, but the complexity of the code is a huge impediment to a product teams’ ability to deliver them to consumers with any speed. It also creates huge learning curves for new developers who are more likely to break working code when applying changes. In addition, the high coupling within monoliths also tends to create private data silos which makes the data inaccessible to other applications, limits insights, and can inhibit growth. If releases of monoliths are delivered with new features, operations teams likely have no idea how the changes may impact resource usage and scaling in existing deployments adding to the overall uncertainty and chance of success. Microservices architecture promises to solve the shortcomings of monolithic applications. By contrast, it encourages applications to be constructed from independent, single purpose microservices, each encapsulating a specific task or business capability. If we were to re-imagine the monolithic “warehousing” application, we would seek to create small microservices that have high cohesion around related tasks that operate on a clearly defined subset of data they own. In this example, we would separate out the Inventory, Processing, Shipping, and Receiving functions into their own microservices. Today, cloud-native services typically document their APIs using the OpenAPI (a.k.a. “Swagger”) standard providing a clear contract on how to interact with them in a self-service manner. Microservices would use these APIs to communicate with each other (over a shared network) to accomplish system tasks, keeping them loosely coupled. These standardized definitions can also be published to a service catalog, allowing their respective services to be discovered and reused by other services. For example, a separate “User interface” service could be added to bring together each of the “warehouse” microservices’ APIs under a unified view. Another principle is that each service manages its data independently as well as often using their own datastores that best suit their data needs. OpenAPI definitions can also be used to automate the generation of documentation, servers and clients, functional tests, and more. Additionally, each microservice can have an independent development lifecycle, assuring the agile delivery of improvements and new features in a granular way. As each microservice is released within (containerized) packages, DevOps teams can easily update (in-place), manage, and scale them. You should now be familiar with: The three development principles for modernization, How monolithic applications are architected and its drawbacks, and How to architect using a Microservices approach and, by contrast, its advantages.