65

I'm learning about microservices and I'm gonna build a project with a microservices architecture.

The thing is, one of my team mates want to use one database for all services, sharing all tables so "data doesn't get repeated", each service would be built with different frameworks and languages like django and rails which use very different ORM standards.

What would be the correct approach? Since I think working with one database would involve a lot of "hacking" the ORMs in order to make them work correctly.

Oswin Noetzelmann
  • 9,166
  • 1
  • 33
  • 46
Eduardo Veras
  • 961
  • 1
  • 7
  • 20
  • 5
    Why would you need to "hack" the orms? Just because they have different syntax doesn't mean they don't basically do the same thing in the end, query the db. – Eyeslandic Apr 25 '17 at 14:07
  • 1
    Possible duplicate of [DB design for microservice architecture](http://stackoverflow.com/questions/43426699/db-design-for-microservice-architecture) – Constantin Galbenu Apr 25 '17 at 18:05
  • It's not a matter of opinion, you *CAN* use a shared database; but you just need to separate access permissions for exclusive access to enforce ownership of data. The Cars table can be owned by the Cars Service. This is already useful, but interestingly, an orchestration service MAY JOIN to the Cars table via a View on a read-only basis. The View enables maintenance of the Service contract. (Unfortunately the question was closed, so I can't elaborate much) – Kind Contributor Nov 06 '21 at 00:45
  • You can, but you shouldnt. Or rather, if you’re sharing a database why are you bothering with microservices at all? – Robert Perry Jan 23 '22 at 13:54

2 Answers2

110

You are not likely to benefit from a Microservices architecture if all the services share the same database tables. This is because you are effectively tightly coupling the services. If a database table changes all the services will have to change.

You have to understand that the whole reason for a Microservices architecture is to reduce dependencies between development teams and allow them to move ahead independently with fast releases.

Here is a quote from Werner Vogels, the Amazon CTO (Amazon pioneered a lot of the Microservices style architecture):

For us service orientation means encapsulating the data with the business logic that operates on the data, with the only access through a published service interface. No direct database access is allowed from outside the service, and there’s no data sharing among the services.

For more information read this and this.

An update in 2021:

Some commenters pointed out that sharing a physical DB may be ok, for example by using separate tables or schemas for different services in the same DB. This is of course possible and still a useful separation of concerns for the service development. It is an architectural (and also organizational-) decision if you want the service teams being responsible for the whole service stack and deployment, including infrastructure, or if you want to separate that out into an infrastructure- or devops-team. Each approach can have its pros and cons depending on your organizational circumstances, scale, requirements, etc.

Another aspect is that newer, scalable DB technologies are becoming more popular. They generally abstract storage and compute for separate scalability and are used as a service (for example Snowflake, Teradata, BigQuery, etc.). They allow growing to very large sizes with millions of tables and petabytes of content using a single cluster. With those it would be the goal to have the microservice implementation teams not worry about the details of running a DB infrastructure, but just use the DB cluster endpoint as a service dependency. And it would be the normal case to have many services depend on that same DB cluster. However you would still want to pay attention to storage separation, e.g. separate logical tables, collections, or whatever makes sense in the specific DB technology.

Oswin Noetzelmann
  • 9,166
  • 1
  • 33
  • 46
  • 16
    This answer is patently false. You can still benefit immensely from using micro-services even if they share the same database. And no, the whole purpose of micro-services wasn't to reduce what you described. That is but one of many reasons. My company converted a monolithic application into 5 microservices and it dramatically improved both our workflow and the performance of the application....but it uses a monolithic database. – gshauger Jul 09 '20 at 14:53
  • 8
    @gshauger: Glad to hear you could benefit from your refactoring. It sounds like you used this to more correctly componentize your application. And your application is probably running at a different scale in terms of complexity, staff size and horizontal scaling requirements than the scenarios that the Microservices architectural style was invented for (Amazon, Netflix, Google with 100s of services etc). Smaller scenarios are of course much easier to handle with the additional dependencies from sharing a DB. I recommend you read up on SOA (which existed before the Microservices term). – Oswin Noetzelmann Jul 09 '20 at 17:50
  • 7
    I'm fully familiar with SOA. I'm also familiar with the fact that the initial proposal for microservices didn't care about the size of a company and it made no mention of a shared database. In terms of "loose coupling" it merely suggested that you select things "depending on what fits best". You seem to have a very narrow definition of a microservice. – gshauger Aug 19 '20 at 22:16
  • 2
    I agree with @gshauger. In some cases you can achieve a service's data privacy by implementing a private-table or private-schema per service in a single database. Of course, in some cases it could also be that some service must have its own db due to throughput requirements. But i don't think it is a MUST to have a db per server... – jim Feb 01 '21 at 12:39
  • @jim : I don't disagree. And I don't exclude that in my answer. Another point is considering new DB technologies that abstract storage from compute. With those it is even less important and many services may use the same logical and/or physical DB as a service. You still want a separation of scope though, and you propose to do it through separate tables or schemas, which may work fine. Depending on the DB technology there may be other ways to cut out your service scope and avoid overlaps. And nothing is to be taken religiously. With good reasons you may deviate of course. – Oswin Noetzelmann Feb 03 '21 at 04:25
  • It really depends, a hierarchy of microservice could have shared database where lower level components(microservice) have views limited to their scope and own write access to attributes in their views, while a higher level component/microservice orchestrating the lower level components could add its own fields (in the same table or a different table), have read access to the entire view, write access to owned attributes. – Abhinav Atul Apr 02 '22 at 07:19
  • Hi @gshauger, thank you for sharing your experience. Out of my curiosity about the performance improvement, is the compute resource (CPU +RAM) for your new architecture the same as the previous architecture or not? Just want to make sure that it really comes from the service splitting but not the compute resource. Want to dive deep into why would splitting the service at code level alone would increase performance if the whole system still have the exact same compute resource and doesn't distribute the load through more databases. – Turbo Oct 12 '22 at 16:36
17

In general a microservice should be responsible for it's own data. That's a perfect world scenario.

In practice some of the services may be highly related to each other. E.g. CustomerShippingDetails and CustomerShoppingCheckout services may both access the same data - customer address. How would you then solve a problem of providing customer address to the customer checkout service. If the checkout service queries the shopping details directly then you break loose coupling between services. Other option is to introduce a shared database.

There will always have to be some kind of compromise on the architecture. What is sacreficed is an architectural decision that highly depends on the big picture (the design of the whole system).

Not having too many details about your system I would go with a mixed approach. That is, having a shared database for services that take care of similar business logic. So CustomerShippingDetails and CustomerShoppingCheckout can share a database. But a StoreItemsDetails would have a separate database.

You can find more about shared database pattern for microservices at Microservice Architecture.

PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
  • 1
    You have a client details service? – Sam Redway Sep 25 '18 at 11:48
  • Depends on what this service would be responsible for. If it handles details of the person - sure. If it handles the details of the person plus shopping details plus shipping etc. then I would break it down so that the microservice has a scope limited to very precise domain - so that it's easy to substitute if needed. – PiotrWolkowski Sep 25 '18 at 15:25
  • 16
    The pattern you are referring to is called an anti-pattern here: https://microservices.io/patterns/data/database-per-service.html Loose coupling is not broken if a checkout service retrieves the address using an API. Loose coupling would be broken if you tie the two through a schema dependency. – Marcin Susel Aug 15 '19 at 12:35
  • 1
    How about having one dedicated microservice to talk to database and rest all the other microservices should make call to that service? One of the biggest advantage is that in future if we migrate to another database (say from SQL to Mongo) then we just have to update that service and none of the other service needs to be aware. – TechTurtle Apr 06 '20 at 23:25