4

Our team of 5 members are managing a microservice architecture that currently includes around 200 Java Spring boot microservices, with approximately 50 new services being added each year. We follow domain-driven design principles and use Spring Cloud Gateway as the entry point, integrating with various systems. Our typical flow looks like this:

Client -> Client Integration Service -> System X Integration Service -> System X

Communication is handled via REST and queue services.

We're encountering several challenges as the number of microservices grows:

  • Maintenance Overhead: Upgrading to a newer version of Java required 5 sprints, primarily due to deprecated objects and the need to update the entire codebase. This process highlighted the difficulty in managing upgrades and deployments across many services.
  • Thin Services: Some microservices are running with only one or two REST endpoints, which seems inefficient. This raises questions about whether consolidating them into a modular monolith could improve reusability and reduce overhead.
  • Resource Consumption: The resource usage of numerous microservices compared to a modular monolith architecture is also a concern, as it affects scalability and operational costs.

I've researched Spring Modulith and modular architecture, but found a lot of controversial discussions suggesting that microservices are inherently better. Tools like Renovate Bot are useful for upgrading simple dependencies, but significant updates like Java require changes across the entire codebase, especially if deprecated objects are involved. On the other hand, the resource consumption of numerous microservices compared to a modular monolith also raises questions.

Question:

  • Given these challenges, would transitioning to a modular monolith architecture help manage the increasing number of microservices, improve reusability, and streamline maintenance?
asked Jul 25 at 10:10
4
  • Can you enumerate any benefit you get from having 40 MS per developer? i.e. some benefit you wouldn't have with 10 or even 5 per dev? Commented Jul 25 at 17:26
  • what the hell - 50 services each year? +1 though Commented Jul 25 at 22:31
  • 1
    One team of 5 managing 250 services by next year? πŸ˜‚ The rule of thumb is that each team should be occupied full-time managing one service! Commented Jul 26 at 8:47
  • I'm new to the team and trying to understand why things are done this way. It seems we're at the center of the company, handling all system interactions, and yes, we're understaffed. πŸ˜„ I'm looking to optimize by merging some microservices into sub-domains, but some architects have said that's not a great idea, hence my question. πŸ˜„ Commented Jul 28 at 8:01

2 Answers 2

7

Ok this is gonna be brief. You're just decomposing to an absurd degree. That's simply it.

Look, forget the names and this and that. What benefit would you realize out of decomposing so much? Because that sounds like you took the convention and went with it blind.

You should decompose to microservices when a monolith becomes unbearable; either it assymetrically requires scaling, or the teams are like that and you can get away with it, technically.

You're introducing distributed computing problems into functionality that's begging you to be local, simple - just like momma used to make it. And the fact you use REST to communicate between them sounds like handling a long brittle chain made of paper-thin crystal.

Microservices have costs. Managing 40 of them would have me flinging grenades into the office by week 2.

https://microservices.io/post/antipatterns/2019/05/21/antipattern-more-the-merrier.html

Consider where the boundaries of your system are. Which services are related?

Create groups.

  • Which entities require independent scaling?
  • Which entities must be updated transactionally and would be awkward to handle cross-service? A 2-phase commit protocol isn't gonna cut it
  • Which have exotic requirements that would jeopardize the operations(deployment, runtime performance/stability) of another?

Consider these and the borders of each of your services will start to appear.

If none of the above applies, domain-driven. Model your services to your domain entities - but this is the same trap since if you've reached this point you're cruising for a reason, rather than having an actual one.

answered Jul 25 at 22:38
3
  • The problem is that we have too many systems around us, all wanting to integrate with each other, and we end up acting as a proxy. I know tools like IBM API Connect can help with this, but until now, we've been handling it through separate microservices. Yes, you're right, we could establish some boundaries. That's what I'm trying to do right now. I'm thinking of consolidating for example five microservices under a specific sub-domain into one, instead of maintaining multiple separate ones. Commented Jul 28 at 10:49
  • Marking as solved due to the typically useful material provided about microservices and their patterns. Thank you. :) Commented Jul 29 at 10:18
  • 1
    You have too many systems around you but at the same time you have a team with finite patience and a brain with finite capacity. Low coupling isn't a standalone saying, it's full-form is "low coupling, high cohesion"; there's a reason for that. So you're gonna have to actually do the engineering part where you make a personal, reasoned, executive decision and say regardless of the clamoring of this authority guy, and this other book, my situation requires X/Y/Z and this is what's gonna happen - slowly and steadily. Don't panic and dump it all for the extreme opposite. Commented Jul 29 at 14:48
3

It sounds like you might actually be managing your project conceptually as a modular monolith. With a small team, a monolithic approach in general would be easier for you to maintain.

Rather than changing the existing implementation, the solution might be to actually embrace microservices properly, or at least to revise the boundaries between services. How are you justifying the contexts for the thin services or have you really split what is conceptually the same domain across multiple implementations.

Would adopting a modular monolith architecture help manage the increasing number of microservices and improve reusability?

Modular monolith makes the code easier to manage and allows code contracts and definitions to be re-used across the modules. If you have a single solution or try to manage the code in a single repo, then you will find modular monolith a lot easier to manage. This is especially true if you have a small or single team of developers, modular monolith suits this much better and saves a lot of boiler plate code and a lot of people, idea and project management.

By definition, yes reusability is improved, but it brings with it a degree of coupling that may make it harder to scale out if or when you need hyper-scale proportions. When that becomes a problem, then you may consider moving back to microservices.

Would adopting a modular monolith streamline maintenance?

Yes, sort of, but also no. The maintenance is different, depending on your specific issues you might find it is worse. The tighter coupling means that when dependencies change, more of the system is inherently affected and needs to be re-tested and re-deployed as a homogenous system. But the same goes for additions of functionality or refactoring for optimisations, small changes can end up having significant impact on the rest of the system and deployment timelines.

Modular monolith centralises maintenance, but the coupling can be constraining and make pushing out simple changes a lot more complicated than implementing similar changes to individual microservices.

However for a small team, the coupling allows you to make significant changes and significant impact across the solution with minimal effort.

Are there best practices or strategies for efficiently handling upgrades and maintenance in a large microservice ecosystem?

In a properly architected microservice ecosystem, each service has its own SDLC and could very easily be running it's own independent code runtimes and languages and may even have it's own backend database or store. Each service implementation is even likely to have it's own dedicated team of developers.

Some services may not need to be upgraded and may be functioning well on older runtimes, this is normal, the idea that you deliberately bring all services up to the same runtime says more about your development team and strategy and means you are more likely running a monolithic development team and trying t make it look like a text book implementation of microservices. Even if you have a corporate policy that mandates upgrading to approved frameworks, you should be able to target each service independently, be able to upgrade, test and migrate into the production environment without having any affect on other services.

If there is significant coupling between services that means they all need to be upgraded, then the best practise for large microservice implementations is to break this coupling. That allows you to manage the ecosystem more efficiently, by not trying to manage the ecosystem as a whole.

How can we balance scalability and flexibility with the operational challenges of maintaining a growing number of services, especially when some are thinly scoped?

Thinly scoped only impacts the number of services. A thinly scoped service as you have described it is easier to test and maintain and likely has less maintenance overheads because it has a narrow interface scope that is less likely to change. A narrow scope is much easier to define and test and therefore easier to get right the first time.

If you have lots of really thin services that utilise the same backend or share similar aggregates and or fault domains, or that are straight up tightly coupled, then you might find the code and dependencies easier to manage if you bundle them up into a single service.

Your problem might not be microservice vs modular monolith frameworks, it might simply be how and why you choose to isolate functionality into new services. Review how you are defining your bounded contexts.

answered Jul 25 at 13:18
1
  • 1
    Well put, top to bottom. @User1254, pay close attention to the last two paragraphs. Often times, "too many microsrvices" indicates things have been separated too much. People see "micro" in microservices, and incorrectly think each service should be really small. Staying true to "independently deployable and scalable" goes a long ways towards mitigating this. Commented Jul 25 at 22:13

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.