While at a macro architecture level, the above patterns are great to create very extensible and highly efficient architectures, the internal structure of your microservices also needs to be taken into consideration.
This is why I also wanted to quickly cover the idea of common components for your microservices.
All the patterns listed here show you how to break the monolith pattern into multiple services. We all know the benefits: it simplifies the task of working with multiple teams, extending or updating a single service doesn’t have to affect the rest (like it would with a monolithic service), and scaling individual services is also faster and easier.
However, having many teams working in parallel in several microservices can be a real logistics challenge if you don’t take the required precautions. Essentially:
- Don’t repeat code, try to keep the coding efforts between different teams as homogeneous as possible. Don’t force them to re-invent the wheel when others already have it.
- Make sure all teams work in the same way. Keep the same standards across different teams to make sure sharing people between them is easier.
- Have an easy mechanism to use other’s code. In line with the first point, it should be very simple to use other team’s code simplifying the development efforts and reducing times.
- Make sure it’s easy to discover what others are working on. When several teams are working in parallel, sharing their work with each other to help re-use is not trivial. Sometimes teams end up re-implementing the same libraries simply because they don’t know what others are already doing.
If you don’t pay attention to these points, you’ll end up with increased development times due to re-implementing solutions multiple times (like logging libraries, common validations, etc), difficulty sharing knowledge between teams because they don’t follow the same standards, and increased onboarding times when moving people from team to team due to the same fact.
How can you plan for this?
My suggestion is to keep this in mind from day one, all your efforts should be towards providing your developers with the required tooling to enable this.
- Define a single working development environment to share between all teams.
- Share common modules either through standard installs, as well as full source code importing them. Both cases will give you access to the module like any npm-based installation would, but the second also gives you access to the source code in case you want to extend it and export it back to the central repository. This is a major win over other Node.js package managers, which only let you install modules.
- Discover what other teams are working on and if you can re-use their modules through a central marketplace which can be both public (if you’re hoping to open-source your company’s work) or private, giving you the exact same list of features.
- Compose and deploy microservices. When using Bit, you decide which independent components are shared and used across microservices, and which components are full microservices that are deployed independently.
Through Bit, you can abstract concepts such as “linter”, “package manager”, “bundler” and others and only focus on the actual workflow. Instead of checking whether you’re using npm or yarn or pnpm, just worry about using
bit install . This bridges the gap between team members who know one tool or the other, and standardizes the way all teams work.
Granted, you can do the same through a set of well-defined standards and individual tools. That is entirely possible and I’ve seen it work myself. However, why would you go through the extra effort of writing and setting all those standards yourself if a single tool can do it for you?