Microservices Development – How to Ensure Services Do Not Share Data

development-processdockermicroservices

I currently have a monolithic web application.
Some API calls need a lot of processing resources and I would like to take that part out of my "backend" monolith and put it in its own service.

I use Docker Compose to develop my application. My database is a MongoDB replica set, to simulate what I have in production, which is a 3-nodes replica set on MongoDB Atlas. My containers in development look like this:

  • frontend
  • backend
  • mongo0
  • mongo1
  • mongo2
  • redis

I've read about microservices and it seems to be highly recommended that distinct services should not share data. I've never worked with a microservices architecture before, but the arguments for not sharing data made sense, so I intend to follow this advice.

So this would mean that if I split my "backend" in 2 parts, let's call them "backend" and "backend-heavy", each one would need its own database.

In production, on MongoDB Atlas, I will probably spin up another database for "backend-heavy", or even possibly another cluster. Then, I will run my "backend-heavy" service separately from "backend".
But now, I'm wondering how my development setup would look like. Would I need "mongo-heavy0", "mongo-heavy1" and "mongo-heavy2" for my "backend-heavy" service, like this?

  • frontend
  • backend
  • mongo0
  • mongo1
  • mongo2
  • backend-heavy
  • mongo-heavy0
  • mongo-heavy1
  • mongo-heavy2
  • redis

What if I eventually want to take another part of my backend and make it its own service? Would I need another 3 containers for this third service as well? It doesn't really make sense to me.
By the way, the reason I need a replica set in development is because some MongoDB commands, such as transactions, are only available with a replica set. Also, I like having my development setup as close to my production setup as possible.

Thank you!

Best Answer

But now, I'm wondering how my development setup would look like. Would I need "mongo-heavy0", "mongo-heavy1" and "mongo-heavy2" for my "backend-heavy" service, like this?

The essence of the microservices approach is that each service can be developed, tested, and deployed independently - potentially each one can be owned by a separate team.

So you would have an independent development setup for each service, and you would only have that one database as part of that setup.

Think if it like if you have an ecommerce application that uses stripe or paypal payments - you don't have your own development copy of stripe or paypal inside your development environment. You either connect it to the real the product, or you make some very simple fake version that's just enough to test your own system.

I can't tell you for sure whether traditional monolith, distributed monolith (i.e. components that are run on separate servers but share one dev setup and have to have matching versions tested together), or microservices is the best approach for you. Look carefully at the pros and cons of each, and take care not to confuse a distributed monolith with microservices.