In a series of blog posts, I am describing an opinionated Node.js microservice architecture.
For the development of a microservice, there are plenty of frameworks and languages to choose from. Many of these options like Java with Spring Boot and Node.js with Nest.js come with a pre-defined architecture and a set of libraries. This allows for a quick start bootstrapping a service. There is one clear and defined way on how to structure the service. There is documentation of a solution for many of the common problems.
However, after a quick start, such frameworks can become a burden. Configuration- and annotation-heavy as they are, they take away choices you could express in code in exchange for hiding complexity. Anything away from the common path like adding your own custom authentication mechanism or introducing a different logging mechanism like JSON-logging requires more work and more complexity with the framework and might even not be possible at all.
For that reason, I avoid frameworks.
Instead, I am defining an own loose architecture and choose and connect own library choices. It allows me to express solutions to problems close to their inherent complexity. It gives me the ability to exchange each library and each functionality if there is a need to.
However, this approach gives less guidance on how to structure an application. With multiple developers working on it, consistency can get lost if a desired structure is not defined. Also, there is no advantage of a quick start since you need to start for each service from scratch. That's where this opinionated architecture guide comes in.
I am describing an opinionated architecture that my team successfully used for three microservices. Over the series of posts, we investigate a dedicated example microservice that I assemble out of the experiences with the three microservices. We talk about various aspects like organizing controllers, configuration management, database connection and querying, API testing, authentication, CI and CD workflows, Kubernetes runtime and more.
From the presented architecture example, you will be able to bootstrap your own production-ready microservice. You will be able to exchange individual libraries to accommodate for your own requirements. You will be able to choose a different architectural structure where you need it. You will be able to harness the full power of a Turing-complete programming language, not being limited by pre-determined choices of a framework.
Become a GitHub sponsor to access the code of the entire series as a GitHub repo.