## 1 Introduction  
Traditionally, software systems were for a long time developed as monolithic systems with a monolithic architecture. As a result, software systems were built as a single unit in which different functional aspects, such as data input and output, data processing, business logic, error handling, and user interface, are interconnected and interdependent rather than loosely coupled [1]. In this tightly coupled monolithic system, each component and its associated components must be present for code to be executed or compiled. Provided that the system is not too large, this architectural style can be applied for small teams and small applications and can be easy to develop, debug, and test. However, with the increased size and complexity, monolithic architectures have to cope with serious disadvantages [2]. The start-up time of larger monolithic applications may slow down. Small changes in a single function can require compiling and testing the whole system, and thus maintenance and evolution of the system will become difficult. For each update, a redeployment of the entire application is necessary, and continuous deployment is difficult. To cope with the obstacles of this architectural style, the notion of service-oriented architecture (SOA) has been proposed [3]. SOA services are provided to the other components by application components through a communication protocol that describes how they pass and parse messages using description metadata. The metadata provide the functional characteristics of the service, as well as the quality-of-service characteristics. Software components are made reusable via service interfaces, which utilize common communication standards and protocols over a network. A service is defined as a discrete unit of functionality that is made accessible by developers, and which can be remotely accessed and acted upon by other users [3; 4]. Examples of services are checking inventory, retrieving a credit card statement online, and payment. A large software application can be provided by using and composing different services. MSA can be considered as a variant of the SOA, which includes a collection of loosely coupled services. In MSA, services are small in size, autonomously developed, independently deployable, and decentralized, while the protocols are lightweight. An MSA is assumed to have the following properties: (1) it lends itself to a continuous delivery software development process. This implies that a change to a small part of the application only requires rebuilding and redeploying only one or a small number of services. (2) It adheres to principles such as fine-grained interfaces (to independently deployable services), business-driven development (e.g., Domain-Driven Design (DDD)). The goal is that teams can bring their services to life independent of others. Loose coupling reduces all types of dependencies and complexities, as service developers do not need to care about the users of the service and they do not force their changes onto users of the service. MSA gives importance to autonomous and lightweight services [4]. MSA has been in more demand because it minimizes the disadvantages that come with SOA and it has a lightweight architecture. MSA can be deployed, developed, tested, and operated independently. MSA has been widely addressed in the literature and discussed from various perspectives [5]. In addition, several vendors have provided their specific solutions in the state of the practice, each with its challenges and benefits. Yet, selecting and implementing a particular approach is not trivial and requires a broader overview and guidance for selecting the proper solution for the given situation. Unfortunately, no study has been provided that reflects on and synthesizes the key features and challenges of the current MSA solutions in the state of the practice. The main contribution of this article is a general framework for characterizing MSA platforms.