They say the old must make way for the new but not everything old is bad. But is that the case with legacy applications that hinder a business’s ability to innovate, pose security threats, and often slow down the overall performance? You probably know where we’re going with this, but let us continue. This article will go over ways to modernize legacy systems and cover the most widely used method – breaking down a monolith into microservices. We’ll describe its characteristics, benefits, challenges, AWS portfolio of products, and finally some tips on how to implement microservices.
The dangers of the legacy systems
Legacy applications are systems that are based on outdated technologies and could have been around in a company for ages. They can no longer be supported by the vendors, it becomes next to impossible to find specialists who could maintain them, maintenance costs eat up all the budget, and most importantly, such systems do not allow adding new features with ease or at all. According to a survey conducted by Accenture Research, 66% of C-level executives would like to replace all of their core legacy systems.
It all can look scary enough for you to feel the urgent need to get rid of your legacy systems now, but we would stop you right there. Because not everything old is bad. Some parts of your legacy application could be kept unchanged, some could be reused or rewritten. It will save the budget and the nerves that come with the total replacement. Just remember that before deciding on how exactly you should deal with your legacy system, it is best to consult technical experts.
Once we’ve established that we are avid supporters of legacy application modernization services, let us tell you the best way to do it.
The best thing you can do with legacy apps without replacing them completely is to modernize them. And there are a variety of ways you can do it: encapsulate, rehost, re-platform, refactor, rearchitect, or rebuild. We’ve covered each of these approaches in detail in our blog post dedicated to legacy system modernization. For the purposes of this article, we would like to touch upon one widely used method in a majority of these approaches – adopting microservices-based architecture.
This brings us to the next topic in our agenda, what are microservices, anyway?
What are microservices?
Microservice architecture, or simply microservices, is a cloud-native approach to building an application so that it comprises many smaller services that are loosely coupled, independently deployable, and highly maintainable. Despite being developed and maintained separately from the other microservices, they all communicate over a combination of REST APIs or through events. Each unit is typically owned by independent development teams, which gives more flexibility to the result-oriented development process and makes such an app easier to scale.
In contrast, monolithic applications are developed linearly as a single unit and are difficult to scale as they require vertical scaling. Why are they called ‘monolithic’? Because the source code for the entire app is built into a single deployment unit like .war or .ear. To scale a monolithic application, developers must increase the whole system’s capacity, disregarding which part of the system is experiencing the most load. Such solutions are self-contained entities.
Many legacy systems were built with a monolithic approach, using a single code base for the whole application. Such an approach was proven to be less agile to innovations because with monolith one cannot introduce new features rapidly and stay on top of the market. To make any changes to the monolithic system, the whole system must be re-built and re-deployed to an updated version.
|Use a single development stack for the whole system||Different stacks for each unit according to requirements|
|Tightly coupled – changes to one component may affect others||Loosely coupled – changes to one component do not affect others|
|Whole app needs to be redeployed with a small change||Self-contained and hence, deployed independently|
|Failure of one component can bring the entire system down||Failure of one component does not bring the entire system down|
|Scaling can often be a challenge||Only the busy component needs to be scaled|
|Large team which can be difficult to manage||Each service is built by a small team that can iterate faster|
|A new developer has to grasp the logic of the whole application||A new developer needs to understand only a particular microservice|
It comes as no surprise that business owners of monolithic legacy systems are taking a microservices approach. If you’d like to learn more about the pros and cons of using monolith or microservices architecture, read our article.
Simply put, microservices development entails restructured teams and such architecture that is already prepared for failures, future scalability, and adding new features. Scaling or making incremental updates does not require a massive effort. We’ve gathered together the most typical characteristics of microservices and described them below.
Characteristics of microservice architecture
- Autonomous multiple components. Microservices are essentially multiple small (hence the micro-) component services that can be developed, deployed, operated, and scaled independently without interfering with other components. Because of that, there is no need to redeploy the entire application if you would like to modify one of its parts. The communication between the components is conducted via well-defined APIs. Each microservice is developed and maintained by a single development team, which gives more developer independence and freedom. Small teams can iterate and scale the services faster.
- Specialized for business. Each microservice covers a single business capability, a single part of the functionality, and it makes this type of architecture centered around business capabilities and priorities. Unlike the monolithic approach where different teams each have a different specific focus, each microservice is developed by a cross-functional team. This team is completely responsible for developing, deploying, running, and maintaining the service.
- Simple routing. Microservices function via a simplified routing method, receiving requests, processing them, and generating the appropriate response. Unlike Enterprise Service Bus that is used for communication in similar service-oriented architectures (SOA), they have smart endpoints that process data and apply logic.
- Decentralized. Microservices are independent and autonomously developed. Compared to the monolithic approach, where a single logical database is used for different services, each service has its unique database in microservices. If one component fails, the others will continue to function and there’s no need to modify all services. Such individual components are easier to use for continuous delivery and complex deployment.
- Failure resistant. A microservices system is fault-tolerant in a way that it keeps the application operational even when some components have failures. When one service fails, it is isolated from others and this allows other components to function. This gives the developers the freedom to develop and deploy services without waiting for the failure to be fixed.
- Evolutionary. Sometimes developers cannot predict what type of devices will try to access the application in the future. In such a case, they choose microservices architecture which is evolutionary in design. Legacy systems that were developed as a monolith, for this very reason, can be redeveloped into microservices.
Benefits of using a microservices approach
Due to containerization technology that allows separate software systems to function simultaneously in the same environment, and Docker that helps manage containers, microservices are the foundation for cloud-native applications. Containerization and the power of the cloud combined, offer numerous benefits for businesses that choose to implement microservices.
- Easier & faster deployment. Because of its modular nature, the microservices approach supports agile development principles and enables continuous integration and continuous delivery (CI/CD) within the individual components. Teams can iterate faster, and quickly roll back new features in case they don’t work without affecting the entire system or other services in the process.
- Defect isolation & system resilience. Microservices enable quick isolation of services that go down keeping the other services running as usual. Such mishap doesn’t take down the whole system as it happens with monolithic applications and this makes the microservices approach highly fault-tolerant. This feature also increases the system’s uptime, an important metric for any business.
- High scalability. Sometimes some services are in more demand than others. Businesses can thus notice a need to increase their capacity by adding supplementary containers with the identical codebase and the microservices model allows them to do just that. Independent scaling also allows to maintain the system’s availability during scaling of some components and to measure more accurately what the new feature will cost.
- Agile development due to small teams. Microservices are developed by independent small teams, often called two-pizza teams – of such a size that two pizzas per team are enough to have for lunch. Small teams are more agile, have faster development cycles, and can iterate faster.
- Technological flexibility & freedom. As a rule, each microservice has an independent development team that has the freedom to choose the best technologies for the functionality. There is no need to follow one technology in the development of all microservices of the system. Teams can choose the best tools to solve their specific problems and not just succumb to old technologies because they were used at the earlier stages of the development for other services in the system.
- Easy to understand. The application is broken down into smaller components that are isolated and less dependant. This makes it easier for the new developers to understand the code, update it and work within agile development methodologies.
- Service reusability across business. A business can re-use some services if their functionalities could be implemented elsewhere across the business. The source code of some modules can be used for multiple purposes and as building blocks for other services. By doing this, businesses can save time and resources to expand their capabilities and roll out new features.
What are AWS Microservices?
The Amazon Web Services portfolio provides a variety of easily integrated building blocks and SDK packages that can help you build any microservice-based application regardless of scale and complexity. AWS cloud platform offers a selection of PaaS, IaaS, and SaaS solutions.
Here are some of the building blocks from the vast AWS portfolio:
- Compute (processing power for microservices): Amazon Elastic Container Service (for containers), AWS Lambda (for serverless).
- Storage & Databases: Amazon ElastiCache (caching), Amazon DynamoDB (NoSQL-databases), Amazon S3 (object storage), Amazon RDS (relational databases), Amazon Aurora (database engine).
- Networking services with high-throughput and sub-millisecond latency: AWS Cloud Map (Service Discovery), AWS App Mesh (Service Mesh), Application Load Balancer (Elastic Load Balancing), Network Load Balancer, Amazon API Gateway (API Proxy), Amazon Route 53 (for DNS).
- Messaging: Amazon Simple Notification Service (message publishing and subscription), Amazon Simple Queue Service (message queueing).
- Logging & Monitoring: AWS CloudTrail (API monitoring), Amazon CloudWatch (application and resource monitoring), AWS X-Ray (Distributed Tracing).
- DevOps: Amazon Elastic Container Registry (Container Image Repository), AWS Developer Tools (continuous delivery).
Why choose AWS microservices?
Usually, an app is built using different layers: a user interface layer, a business layer, and a persistence layer. Amazon microservices architecture splits functionalities into vertical layers and each is responsible for a certain function.
A typical microservice architecture on AWS
We’ve described the main stages of app development using microservices below.
The user interface (UI) is the appearance of display screens, pages, and visual elements like buttons or icons – everything that enables a person’s interaction with the device, product, or service. AWS provides the following services for delivering and storing the contents of the website:
- Amazon Cloudfront, a content delivery network with fast performance that securely delivers data, videos, applications, and APIs with low latency and within a developer-friendly environment.
- Amazon S3, an object storage service for hosting static web content built to store and retrieve any amount of data from anywhere.
AWS offers powerful building blocks that help make microservices development easier:
- AWS Lambda, an event-driven, serverless computing platform that can be used with many programming languages. It lets you run code in response to events without provisioning or managing servers. You can upload code and Lambda will take care of everything required to run and scale your code with high availability.
- ALB (Application Load Balancer) distributes incoming application traffic across multiple targets, such as EC2 instances, in multiple Availability Zones. This increases the availability of your application.
- Amazon EC2, virtual servers that run your applications in the cloud.
- AWS Fargate, a serverless container management service that works with both Amazon Elastic Container Service (ECS) and Amazon Elastic Kubernetes.
- Amazon ECS, a service with which Elastic Load Balancing works that enables you to run, stop, and manage Docker containers on a cluster of EC2 instances. It helps improve the availability and scalability of your applications.
Each microservice should have its data persistence layer to be independently scaled. AWS offers a variety of stores that serve different purposes.
- Amazon ElastiCache, a managed service that offers such in-memory caches technologies as Memcached or Redis, widely used stores for session data.
- Amazon Aurora, a MySQL and PostgreSQL-compatible relational database built for the cloud, is one of AWS’s six relational database engines. Relational databases are used to store formatted data for microservices.
- Amazon DynamoDB is used to create a database table that can store and retrieve any amount of data and serve any level of request traffic. Relational databases are not suited for endless scale, and for this purpose, NoSQL databases have been designed. But NoSQL-databases have different access patterns than relational databases, for instance, it is not possible to join tables.
How to implement Microservices on AWS
We’ve covered the types of services offered in AWS portfolio and now let’s talk about how you can begin implementing your microservices on AWS. We’ve put together a rough plan and some tips for you to get some general idea from where to start and what to keep in mind.
Each microservice needs to have its own repository and its own CI/CD pipeline. For this, AWS CodeCommit can be used, as well as any other repository services like BitBucket, GitHub, or GitLab. AWS CodeBuild that builds the code and CodeDeploy that automates software deployment can be used to produce a container – a deployable artifact (i.e. Docker image). Docker images are then pushed to AWS ECR (Docker registry).
The type of microservices interaction depends on the project needs and its domain because microservices communicate differently with each other. Some services can expose REST WebAPI which can be called by different services. The other microservices (the whole system or some parts) can be event-based. In such case, services can produce and react to events happening in other services. To achieve this, you can use AWS SQS message broker. Event-based systems are easily scalable as there are no direct communication between services. All messages are processed by the message broker.
Each service should have its own database which suits its needs. The database is selected according to the project needs and the type of function the microservice performs, which tasks. Some tasks cannot be performed with NoSQL databases and there are tasks not suitable for relational databases. AWS offers Aurora data storage among relational databases and DynamoDB among NoSQL ones. Using AWS Aurora or DynamoDB ensures your data is more available and more protected even in case something happens with the data center. Database technology should also be chosen considering what exactly your microservices are responsible for.
Apart from the above mentioned AWS services, depending on microservice function we can use Load Balancers, Route53 for DNS Rooting or S3 for file storage.
What are the challenges with microservices? The microservices adoption journey is fraught with challenges and concerns for organizations. There are two types of challenges – technical and general. We will start with general and then review the most common technical problems and how AWS overcomes them.
One of the most common challenges businesses face when adopting a microservices approach is the lack of experienced talent who can define which applications are the best candidates for transition to microservices. Uncertainty around security issues might also be a hurdle. According to a study conducted by IBM, 49% of surveyed IT executives noted insufficient internal expertise in DevOps or agile practices. 50% of them mentioned they are having difficulties integrating cloud and on-premises environments. All these concerns can be mitigated by bringing in the right technological partner.
One of the most obvious technical challenges with microservices architectures is getting containerized services to discover and interact with each other. Amazon ECS comes to the rescue – it now includes integrated service discovery that enables services to easily discover and connect.
During API implementation different versions of APIs need to have backward compatibility. After the API is published, the next challenges arise: managing, monitoring, and monetizing the ecosystem of third-party developers. The developers might also need to know how to throttle requests to protect the backend services, cache API responses, handle request and response transformation, and generate API definitions. AWS with its Amazon API Gateway solves these challenges and makes it easy to create and maintain RESTful APIs.
As you can see, with the skilled talent and carefully selected AWS offerings, the transition to microservices can be a painless and easy process.
Breaking down a monolithic application into microservices and implementing them on AWS requires a lot of knowledge and experience. In our article, we have described characteristics of microservices, their benefits, challenges, and constructed a short guide of AWS portfolio of products to give you a better understanding of what and how you can use. Also, we added some typical flow of how to implement microservices on AWS, along with some tips. We understand that choosing the right microservices and implementing them can be a daunting task, so please remember that our experts are always ready to help you.