
We’ve all listened to them. The holy rules of software engineering are transmitted by experienced developers, articles, and presentations at confer...
For further actions, you may consider blocking this person and/or reporting abuse
The problem you are running into are two fold:
1: I agree.
2: Your N+1 problem is a problem you see with many ORM's because they automatically fetch data when accessing an attribute that is a relationship. You need to prefetch the data you want to use or write manual SQL to get the data you need. It is also a team problem that this got accepted to go live. You need to be aware of the SQL your ORM generates.
3: You need to define an API and test the API. I don't know what you wrote and how you wrote it, but you need to think about: How do I want this thing to behave or use it in such a way that is easy for me/us/others to use? You'll want to test contract of your code and not the internal mechanics. Small caveat: It is also important to test the mechanics, but you can do this for specifics. Where you know: This is important to test, because it is a crucial part of the logic of the contract.
Appreciate the detailed breakdown. You're absolutely right about ORMs hiding the N+1 problem - that's exactly what caught me off guard. And solid advice about testing the API contract versus internal mechanics. Thanks for sharing these insights!
Hmm, ever since the concept of microservices started popping up, I've never really heard this "Always Use Microservices" thing. Indeed, the advice is almost always "identify bottlenecks, then carve out that functionality into a microservice as needed".
I would also extend this advice: Use a monorepo. Deployment is easier, devex is better, and sharing libraries (or entities/models) is trivial. It requires good understanding of the project scope of course, but monorepos have become my mantra - I can flip services on/off, scale out as needed, and keep my API as my nerve centre.
As for tests - yes, absolutely write them. But focus on the happy path. 100% code coverage is nice, but blimey does it slow you down.
"Later" arrived the moment we onboarded our first beta users
yup. 100%. Big picture thinking and defensive programming will help you in the long run.Great insights!
Yo the monorepo idea is a solid upgrade to my monolith take 👌 That sounds like the perfect middle ground for when you need to scale without the deployment nightmares. Appreciate you sharing that!
these are good observations, but i would submit:
a. 'premature optimization': this really comes down to the definition of when 'mature' is.
b. 'testing': doing tdd right requires a lot of experience. attempting to test everything at the unit level can get you into the situation you described, sure, but unit testing works very well for discreet, ideally pure, functions. committing to tdd changes the way you write code in general, moving your design more towards writing stuff that is more testable.
Good point about TDD experience. It's definitely a skill that changes how you think about code design. Thanks for adding that perspective!
Thanks for sharing your experience, in this world of shallow bragging it's always refreshing to see genuine self-reflection and I think there is a valuable lesson to learn here for all of us: common sense before "best practices". Perfect is the enemy of good, and quite often it's not even perfect.
Thanks Gabor! 'Common sense before best practices' might be the real TL;DR here. Love that line about perfect being the enemy of good - so true in so many contexts 💯
Great post 👍 this is where theory meets practical implementation.
I like that you also included test coverage as an example. It's so hard to convince the industry that the 90% test coverage target is hurting their business.
My ideal test strategy is: write e2e tests for critical user flows and unit tests for the lowest order of (pure) functions. Then, when something breaks after code changes, write an integration test that catches that specific case.
Your test strategy is actually smart frfr. E2E for the main stuff and units for pure functions makes so much sense. Definitely stealing that approach man👏
This post is a great reminder that best practices are just guidelines, not rules set in stone. Adapting architectural patterns, performance optimization, and testing strategies to your project's scale and team maturity is key to sustainable success. Context really is king.
Appreciate that! And well said - 'guidelines, not rules' is the perfect way to put it. Context over everything.
I think with system design, it's important to keep in mind you want to start with a simple system before jumping to a complex system.
With microservices, why try to spin up multiple instances? It's easier to do that once with a monolith, then split off functionality in the future as needed.
For testing, I've found when working on a new project it's better to use tests to lock in the invariant logic. If something is not changing a lot, unit tests can help insure that keeps working into the future. This can be especially helpful when a refactoring is needed at some point.
Exactly - starting simple is the move. Your point about using tests to lock in invariant logic is smart too. Makes refactoring way less stressful later on.
Context is king. This applies to every prescriptive practice. It's like always using a hammer when what you need is a wrench.
Bro the hammer/wrench analogy is perfect 😂 Exactly what I was trying to say. Context really does determine everything. Appreciate you distilling it down to the core truth.
Hi! Here are my two cents. I get where you’re coming from, and your point is clear. Still, there’s one thing I think went wrong. The issue wasn’t “best practices.” It was the early assumption that you already knew exactly what to build and how.
By skipping a POC and an MVP, you missed the chance to validate the SaaS idea and to learn where, if anywhere, it made sense to introduce microservices. Prototyping helps you understand the real challenges; an MVP helps you discover the right stack.
Jumping straight to microservices because they’re labeled a best practice is what led you off track. The problem wasn’t using microservices or thinking about scale. It was doing that before validation.
This hits hard. Best practices often get repeated like laws instead of guidelines. I’ve seen the same with “add more layers of abstraction” — sounds clean in theory, but in small projects it turns into needless complexity that slows everything down. Context really is king.
Nice post!