Let's begin by looking at microservices in more details. Microservices divide a large program into a number of smaller independent services as shown on the right, unlike a monolithic application which implements all features in a single code base with the database for all data as shown on the left. Microservices are the current industry trends. However, it's important to ensure that there is a good reason to select this architecture. The primary reason is to enable teams to work independently and deliver through to production at their own cadence. This supports scaling the organization, adding more teams, increases speed. There's also the additional benefit of being able to scale the microservices independently based on their requirements. Architecturally, an application designed as a monolith or around microservices should be composed of modular components with clearly defined boundaries. With the monolith, all the components are packaged at deployment time and deployed together. With microservices, the individual components are deployable. Google Cloud provides several compute services that facilitate deploying microservices. These include App Engine, Cloud Run, GYVE, and Cloud functions. Each offers different level of granularity and control and will be discussed later in the course. To achieve independence on services, each service should have its own datastore. This lets the best datastore solution for that service to be selected and also keeps the services independent. We do not want to introduce coupling between services through a datastore. A properly designed microservices architecture can help achieve the following goals. Defined strong contracts between the various microservices, allow for independent deployment cycles including rollback, facilitate concurrent AB release testing on subsystems, minimize test automation and quality assurance overhead, improve clarity of logging and monitoring, provide fine grained cost accounting, increase overall application, scalability, and reliability through scaling smaller units. However, the advantages must be balanced with the challenges this architectural style introduces. Some of these challenges include, it can be difficult to define clear boundaries between services to support independent development and deployment. Increased complexity of infrastructure with distributed services having more points of failure. The increased latency introduced by network services and the need to build in resilience, to handle possible failures, and delays. Due to the networking involved, there is a need to provide security for service to service communication, which increases complexity of infrastructure. Strong requirement to manage in version service interfaces with independent deployable services, the need to maintain backward compatibility increases. Now, decomposing applications into microservices is one of the biggest technical challenges of application design. Here, techniques like domain-driven design are extremely useful in identifying logical functional groupings. The first step is to decompose the application by feature or functional groupings to minimize dependencies. Consider for example, an online retail application. Logical functional groupings could be product management, reviews, accounts, and orders. These groupings then form mini applications, which expose an API. Each of these mini applications will be implemented by potentially multiple microservices internally. Internally, these microservices are then organized by architectural layer, and each should be independently deployable and scalable. Any analysis will also identify shared services such as authentication, which are then isolated and deployed separately from the mini applications. When you are designing microservices, services that do not maintain state but obtain their state from the environment or stateful services are easier to manage. That is, they are easy to scale, to administer, and to migrate to new versions because of their lack of state. However, it is generally not possible to avoid using stateless services at some point in a microservice based application. It is therefore important to understand the implications of having stateful services on the architecture of the system. These include, introducing significant challenges in the ability to scale and upgrade the services. Being aware of how state will be managed is important in the very early stages of microservice application design. Let me introduce some suggestions and best practices on how this can be achieved. In memory, shared state has implications that impact and negate many of the benefits of a microservice architecture. The autoscaling potential of individual microservices is hindered because subsequent client requests have to be sent to the same server that the initial request was made to. In addition, this requires configuration of the load balancers to use sticky sessions, which in Google Cloud is referred to as session affinity. A recognized best practice for designing stateful services is to use backend storage service that are shared by frontend stateless services. For example, for persistent state, the Google Cloud-managed to data services such as firestore or Cloud SQL maybe suitable. Then to improve the speed of data access, the data can be cached. The memorystore, which is a highly available latest best service is ideal for this. This diagram displays a general solution that shows the separation of the frontend and backend processing stages. A load balancer distributes the load between the backend and frontend services. This allows the backend to scale if it needs to keep up with the demand from the frontend. In addition, the stateful services or servers are also isolated. The stateful services can make use of the persistent storage services and caching as previously discussed. This layout allows a large part of the application to make use of the scalability and fault tolerance of Google Cloud Services as stateless services. By isolation of the stateful servers and services, the challenges of scaling and upgrading are limited to a subset of the overall set of services.