How It All Began
I was part of a large e-commerce project in 2014. Like all teams back then, we jumped on the microservices train. We tried to develop āmicroservicesā with less-than-optimal frameworks and tools. What seemed like a curse at the time was actually a blessing: operations. There was simply a hard āNo!ā and no possibility to deploy dozens of microservices into a production environment.
Constraints breed creativity, and I learned a tremendous amount back then.
Weāll see how that helped me.
10 fundamental things Iāve learned over the last 10 years developing (micro)services that have proven themselves time and time again.
None of these fundamental learnings are about frameworks or specific technologies. The longer you work in IT, the faster you realize how unimportant all of that is.
But letās get to the promised learningsā¦
1) Microservice, Nanoservice, Vertical, Monolith, Modulithā¦
The distinction of what exactly youāre building doesnāt interest anyone. āHow big should your microservice be?ā - completely irrelevant. The only important thing? How well is what youāre building structured. My recommendation, if I start on a greenfield project today: 100% a cleanly modularized monolith (Modulith). Physical separation is almost always complete overhead. Back in 2012, we were forced to do exactly that, and the result is still in production today, used daily by thousands of people. The structure from back then still holds up today.
2) Data Flowā¦
Probably the most important point on this list. You must be able to explain in simple words how data flows through your service.
āInput via Kafka ā Record is processed ā Aggregate persisted ā Projections via HTTP, Kafka Connect and Kafka Streams provided to the outsideā
If you canāt explain it that simply, something is wrong.
3) Independenceā¦
Regardless of which constellation you develop services in, your service itself must be independent of the environment. If you first have to start Kafka, 2 databases and 4 external systems just to āquicklyā reproduce a problem, something is wrong.
Also, if you donāt have the ability to debug your business logic within 2 minutes, something is wrong. Weāll come to that later.
This learning fits perfectly with streaming-based services with Kafka. If you want to learn more about this, Iād be happy to hear from you.
4) Interfacesā¦
Your service is based on interfaces. The implementation is an unimportant detail. When I design new services or modules, I ALWAYS start with the interfaces and put the interfaces together like Lego blocks. Afterward, I know exactly which building blocks I need. If you only have interfaces, itās impossible to mix concepts that donāt belong together. And you can already write initial tests against the interfaces only. This way, you know the structure is valid. You donāt need a single implementation for this. If the interfaces are structured correctly, the implementation is simple in the end. You can even outsource it. If you donāt know which interfaces you need, something is wrong.
5) DRYā¦
āLIBRARIES IN THE MICROSERVICE WORLD ARE BAD!ā
āWE WANT TO AVOID DEPENDENCIES!ā
Nonsense.
What unnecessary effort, costs, and bugs! Instead of a cleanly structured library, changes are preferably made 3, 4, or 5 times in nearly identical classes. As an architect and also as a developer, I can only wonder how anyone in their right mind can accept this situation. Shared, non-domain functionality belongs in libraries. The ādependenciesā can be easily handled through clean processes. If you have to make changes more than once, something is definitely wrong.
Your team works with Kafka and streaming technologies and you have the feeling itās not running smoothly? You feel thereās a lack of know-how and experience? Maybe we can help. Learn more now. You can also place some technical questions here.
6) Abstractionā¦
This point goes hand in hand with the previously described use of interfaces. Everything external is kept away from the application (abstracted). Infrastructure has no place in your code. A connector class from the Salesforce library? You must wrap it. Build an interface for it. AWS SDK for DynamoDB? Must definitely be hidden behind an interface. The āconceptā is not DynamoDB, the āconceptā is something else. Name your interface after the concept. Why? Your safety net against breaking changes and the assurance that youāre working with the āconceptā and not the āimplementationā. If youāre working directly with the AWS SDK in your business classes, something is wrong.
7) Dependencies
Your dependencies must be cleanly managed. And by that, I donāt mean the ticket the architect opened because of the Arc42 violation. Each module defines an API. Here the interfaces from Learning 4 are defined. You write the API first (can be a separate Maven module, for example). This makes it impossible for other modules to rely on a concrete implementation, since only interfaces are available at compile time. The implementation only comes at the very end. If your dependencies donāt follow a clear structure, something is wrong.
8) Automationā¦
Everything, really everything in your service must be automated. Automation is the key. Tests⦠run completely automatically, of course. Quality assurance⦠you do completely automatically. Documentation⦠is fully automated. Library upgrades⦠you do completely automatically. Deployments⦠you do completely automatically. If you have manual steps that āevery sprintā have to be done again and again, something is wrong.
9) Qualityā¦
Your tests are the be-all and end-all. Especially together with Learning 8)
Unit tests secure the basic functionality.
Integration tests secure the interaction of all modules.
To debug the application, ideally itās enough to start the integration test (thatās the 2 minutes from Learning 3).
10) Fail Fast, Fail Early, Fail Hard.. Repeat
The biggest mistake you can make is āto waitā. Waiting with the library upgrade, waiting with the module upgrade, waiting with the deployment, waiting with⦠whatever. If something goes wrong, then please quickly and in a way that we see it immediately. Automate everything. If the library changes, automatically increment the version in every service and let it crash. The earlier, the easier. If youāre 6 versions behind the library in your service, something is wrong.
Curious? With our expertise in Kafka, Kotlin and Spring, we offer the opportunity to accelerate your development and make it more productive.
An independent architecture review creates clarity about the status quo.
In our free introductory call, you also have the opportunity to ask initial questions at no cost.
Join the Agentic Engineer Program
Apply Spec-Driven Development Hands-On - Event Modeling, Event Sourcing, and AI Engineering with autonomous agents.
Book a Call Today
Want to talk through how Event Modeling could work for your team or project? Letās have a quick, no-pressure conversation.
