Thursday, May 8, 2025

The shared module microservice antipatten

 

The shared module microservice antipatten

Shared modules are a part of every medium sized software project. The different modules in your application need some common code, components, services, or utilities that are used across the application.

 Instead of duplicating this code in different modules, it's placed in the shared module to promote consistency, reduce redundancy, and simplify maintenance. It has been a common practice in software projects to package the shared module as an artifact and make it available to the application through a package manager. For example, in Java, the share module is written as a different code project, packaged as a jar and then pushed to the artifact repository, then the application can use it by adding a dependency and downloading it through the package manager. The same is done for different other languages. 


With the emergence of microservices, I have witnessed where in some projects, developers implemented the shared module not as a library but as a microservice. This results in other microservices having to call the share module microservice for common functions.



 


This is an antipattern. It introduces tight coupling between services, adds network latency, and creates a new point of failure. It also increases operational overhead with more deployment, monitoring, security, and resiliency requirements.


One common defense is that updating the shared module as a service avoids the need to redeploy all microservices. That sounds reasonable—until you consider the tradeoffs:


  1. In the era of automatic deployments and devops, deployment of several microservices should not be such an overhead. It certainly should not force us to abort existing software engineering practices that have been around for years.

  2. The overhead of deploying additional services does not equal the overhead that is introduced by adding an additional microservice. As mentioned, this presents the additional overhead of deployment, monitoring, security and resiliency. 

  3. When making a change to a shared module, you will likely need to retest your application before deploying, since all modules accessing the shared module will be affected, whether the change breaks a contract or not. This will probably lead to additional fixes and deployments, so the thought that we can just deploy the shared module service without additional overhead is rather naive.

Unless there's a strong architectural reason to expose shared functionality as a service—like cross-cutting concerns that truly need runtime access—it's best to stick with well-established practices: package the shared module as a library artifact.


Wednesday, May 7, 2025

Why Tech Depth Still Matters – Even for Senior Architects

 

There’s a common belief in the industry: “As you move up, you should focus more on strategy and less on code.”

While strategy, communication, and big-picture thinking are crucial for architects, there’s one thing I strongly believe:

Tech depth still matters. A lot.

Here are some of the reasons why:

🔹 Bad abstractions create bad systems. If you don’t understand how databases handle transactions under load or how Kafka deals with failures, you might design a system that looks good on paper—but falls apart in production.

🔹 Developers respect architects who "get it." If you can debug a tricky performance issue or explain why a specific microservices pattern is a bad fit for a project, engineers will listen to you. If you only speak in slides and diagrams, they won’t.

🔹 Tooling moves fast, but fundamentals don’t. Kubernetes, serverless, event-driven systems—these are tools. But deep knowledge of distributed systems, concurrency, and scalability will make you a great architect regardless of the tech stack.

🔹 Hands-on experience keeps you relevant. The best decisions often come from personal experience, not just theory. Even if you don’t code full-time, keeping your hands in the tech—through prototypes, reviewing PRs, or experimenting—gives you an edge.

Yes, architecture is about trade-offs, alignment, and long-term thinking. But without real technical depth, those decisions can be shallow.


Monday, May 5, 2025

How to detect the “service sprawl” anti pattern in your microservices architecture.

The service sprawl is an antipattern in your microservices architecture, in which you have broken down your application into an excessively large number of very small services. While aiming for fine-grained control, it can lead to increased complexity in management, deployment, and communication, potentially outweighing the benefits.





I have seen this happen, especially in large IT organizations, that are trying to adopt microservices. It is very easy for developers and managers to fall into the everything-is-a -microservices pitfall.

So, how can you tell if your application, or company is implementing this anti pattern ?

One of the most obvious “red flags” which indicate that you have a service sprawl, is if you find that some of your developers are responsible for developing and maintaining several microservices at the same time.  Of course, it might be that you have an expert developer, working on several projects at once, but this is a red flag that is worth looking into.

There are two main reasons that this is a red flag for the service sprawl:

  1. If each developer can develop and maintain several microservices at once, it likely means those microservices are probably too thin. While that might be justified, still, it’s a good idea to look into that.

  2. If a single developer is developing several microservices in the application, it can also mean that this application does not suffer from the drawbacks of a monolith and maybe those services could be combined into a single application, without the problems that monoliths are notorious for. 


To avoid service sprawl, teams should regularly evaluate whether their microservices are delivering real separation of concerns and justifying the overhead they introduce. Not every boundary needs to be a service boundary. Sometimes, combining overly thin services into one  can simplify architecture without sacrificing modularity. The goal is not to have more services, but to have the right ones.