Usually, a monolith application has a single big data store that stores the data for all the needs of the application. In microservices, we divide the application into independent services. The database per service pattern suggests having independent, scalable and isolated databases for each microservice instead of having a common datastore. Each service should independently access its own DB, services cannot access each other’s DBs directly.
This pattern ensures loose coupling between services, any issues, or changes in one service would not affect any other service or its database. Also, it is not necessary to use a single type of DB for all services. Each service can choose its database according to its requirements.
Let us take examples of some of the most common services that any e-commerce platform requires. The typical Orders flow is handled by multiple services. Two services that the order management system interacts with are item service and inventory service. Item service needs data related to items, their cost, sellers selling it, and inventory service needs data related to how much inventory is left for the items. Both data storage requirements are related, but if we store them in a single database, it will become huge, complex, difficult to manage and the queries (especially joins) will take a lot of time to execute.
To solve this problem, we can use the database per service pattern. An items database will store items data and another inventory database will store inventory data. Items service will connect to items db and inventory service will connect to inventory db. This way, if there is any issue in items service, inventory service will still keep running.
One fundamental problem to solve here is what happens if reading data from both items and inventory databases is required. For example, if I need the item name along with inventory numbers for all sellers selling that item? In this case, usually we would perform a join if there was a single database and two tables in it.
The applications can perform the join instead of the database performing the join. If the items service requires data from inventory service, it can request. The inventory service will have APIs to provide this data. For example, for inventory for a specific item, the item name can be retrieved from the items db, and then using the item id, an API request can be sent to inventory service to get the inventory for that item id. This is known as API composition. One of the ways of achieving this is by using the Saga pattern, as explained further below.
You get the following benefits by using the database per service pattern for designing your microservices.
While it is immensely helpful to use this pattern in large sets of microservices, it is not advisable in the following scenarios: