Problem
What’s the database architecture in a microservices application?
Forces
-
Services must be loosely coupled so that they can be developed, deployed, and scaled independently
-
Some business transactions must enforce invariants that span multiple services. For example, the
Place Order
use case must verify that a new Order will not exceed the customer’s credit limit. Other business transactions, must update data owned by multiple services. -
Some business transactions need to query data that is owned by multiple services. For example, the
View Available Credit
use must query the Customer to find thecreditLimit
and Orders to calculate the total amount of the open orders. -
Some queries must join data that is owned by multiple services. For example, finding customers in a particular region and their recent orders requires a join between customers and orders.
-
Databases must sometimes be replicated and sharded in order to scale. See the Scale Cube.
-
Different services have different data storage requirements. For some services, a relational database is the best choice. Other services might need a NoSQL database such as MongoDB, which is good at storing complex, unstructured data, or Neo4J, which is designed to efficiently store and query graph data.
Solution
To solve the above concerns, one database per microservice must be designed; it must be private to that service only. It should be accessed by the microservice API only.
It cannot be accessed by other services directly. For example, for
relational databases, we can use private-tables-per-service,
schema-per-service, or database-server-per-service.
Each microservice should have a separate database id so that separate access can be given to put up a barrier and prevent it from using other service tables.
Resulting context
Using a database per service has the following benefits:
-
Helps ensure that the services are loosely coupled. Changes to one service’s database do not impact any other services.
-
Each service can use the type of database that is best suited to its needs. For example, a service that does text searches could use ElasticSearch. A service that manipulates a social graph could use Neo4j.
Using a database per service has the following drawbacks:
-
Implementing business transactions that span multiple services is not straightforward. Distributed transactions are best avoided because of the CAP theorem. Moreover, many modern (NoSQL) databases don’t support them.
-
Implementing queries that join data that is now in multiple databases is challenging.
-
The complexity of managing multiple SQL and NoSQL databases