4

As a long-time perpetrator of monolithic systems (oh, the shame!), I recently had my eyes opened to the concept of microservices. I've now read lots of online articles, and enjoyed the piecemeal plan of the Strangler Pattern to break a monolith into microservices. I can see how especially with the advent of technologies like Kubernetes to manage all these disparate parts, it makes a lot of sense to have lots of small services that can be independently scaled and maintained by different development teams.

What's getting me stuck, though, is that everything I've found on the Web talks in abstract generalities, with very little actual code explaining how to do anything beyond CRUD in a microservice. Like, let's take the scenario of an application that has customers and products. There's one piece of the system that manages the sales and billing, and another piece that manages the tech support. What's common between them is Customer and Product. The sales side also has an Order table, while tech support has a SupportTicket.

So, what's the "correct" microservice architecture here, if we have to design this from scratch? Should we have separate microservices for each table? Or are "Sales" and "TechSupport" separate services? If the latter, who gets responsibility for maintaining Customers and Products? If the former, what happens in the event that Tech Support gets a ticket that is billable, and they won't start working on it until they get an Order linked to their support ticket that shows it has been paid? What if business rules require that there needs to be a transaction boundary, so that the support ticket does not get created unless there is a matching, paid order?

I guess my broader question is that invariably, in real-world systems, things have dependencies on other things, and sometimes those dependencies are circular. How is it possible to have all these neat, lean microservices, that do nothing other than worry about their own bailiwick, when the reality is that it's very rare to have the luxury of not caring about anything else in the overall system?

  • 2
    Don't be ashamed of building a monolith. A monolith is a good choice for an architecture in a lot of cases (maybe it still is in your case). – Helena Feb 9 at 18:40
  • @Helena - the way people write about microservices, it sounds like the general rule is "Monolith - BAD; Microservices - GOOD". Yet I'm thinking of all the projects I've worked on over the past 2 decades, and I can't wrap my mind around how any of them would have worked as microservices. I feel like the problem is in the way I'm thinking...so I'm hoping someone here can help me shift my paradigm. – Shaul Behr Feb 9 at 19:46
  • 2
    It certainly isn't that black and white. And you might be interested to learn that some organizations are going back from SOA to monlithic arechitectures. In this podcast it is argued that "monoliths are the future": changelog.com/posts/monoliths-are-the-future – Helena Feb 9 at 20:00
5

It's not about if Monolith, SoA or Microservices are the best architecture. It's about where the bounded contexts are within your design and what the correct architecture for your situation should be.

Having said that, there are usually a few obvious candidates for microservices in each project. For example, I have shipped a microservice that created gigabyte sized application packages with the use of a third party operating system library. We didn't want the knowledge of this API printed all over our codebase, the resource requirements were very different, and we had a good seam where we could seperate how we handled application packages and how the third party API handled them and how we could lock away that translation in a small service.

Microservices are not tied to data. Microservices are an expression of encapsulation. Think about which services could have small interfaces and large internal complexity. Let's say you have order fulfillment which needs to think about the item weight and dimensions, what boxes to choose to fit the items in, which carrier is cheapest, which carrier can ship to PO box, which carrier can offers expedited shipping, which can ship hazardous materials ... you maybe need to APIs, getShippingCost() and printLabel(). These are not things sales or tech support need to be concerned with, so they are good candidates for encapsulation (with the right interfaces)

Now the shipping team can ship the service at any time, rewrite it in golang, rewrite it for another database, ditch a reputable shipping company for underpaid drivers in white vans etc. without affecting the rest of the project. As long as they uphold getShippingCost() and printLabel().

| improve this answer | |
  • Thanks, that is a useful way of looking at it. What about the situation I described in the original question, where you have separate billing and tech support services, but tech support has a dependency on billing, requiring a transaction boundary? How would you do that with microservices? – Shaul Behr Feb 10 at 10:59
  • In a real world scenario, microservices will have dependencies on eath other. However, one can model where the source of truth lies and what additional data is stored in each service. For example several services may store data in relation to the user, but the source of truth for the user ID must be the user service. – Martin K Feb 11 at 0:08
  • 1
    Your scenario is actually what I think of an event streaming scenario more than a microservices scenario. Orders are put in a processing queue until preconditions are met, then put in an approved order queue (or rejected order queue). So this doesn't fit in a request/response pattern like REST APIs are. However, the entities doing the event processing still can be microservices. – Martin K Feb 11 at 0:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.