It might seem obvious, but performance is a concern, and it's easy to make mistakes in that particular matter.
This topic can be quite sensitive in dev teams because performance failures are usually impactful.
🦄 "Too unlimited"?
Indeed, resources like memory are limited. Even if you can enable horizontal scaling, especially in the cloud, it won't cover all cases.
While traffic peaks may happen, unoptimized queries (e.g., databases) or nonperformant loops can put your server under heavy stress.
It's a bit counterintuitive, as local installations (a.k.a dev environments) usually benefit from "unlimited" resources.
For example, it's easy to disable timeouts by allocating all power (e.g., memory) to your script.
Besides, it's a good practice not to replicate all data from the production database.
Not only that it would not be compliant with GDPR (unless everything is anonymized, which is usually not the case), but unrealistic for many apps (terabytes of data).
🤘🏻 Quality is systemic
I also love that post.
Quality is systemic
Good tooling is a great start. If you can set metrics, add performance monitoring (e.g., profiler in your pipelines) and even consider load/scalability tests, you will reduce capacity bottlenecks (e.g., CPU, RAM).
Of course, it does not replace a good approach in the first place, but it will definitely help.
While such additional layers can save the day, Jacob Kaplan-Moss reminds us "there are both technical and human factors involved in systemic quality, and these factors intersect and interact."
Both failure and quality are systemic.
💥 Timeouts, DNS, and "blast radius"
Timeouts can be pretty hard to trace back, especially in big projects.
While it's not uncommon with micro-services that depend on other micro-services (a.k.a. distributed monoliths), it's also difficult with pseudo-monolithic codebases that actually rely on various external services and HTTP requests.
Besides, DNS failures happen.
Love that presentation by Pascal MARTIN (French, but you might be able to get it translated), especially when he explains the concept of blast radius.
🙈 Nonperformant code
This is where your approach can save some time. It's best if you can avoid the following situations:
- complex calculations in the code while the database could do it (e.g.,
SELECT COUNT
with SQL) - heavy operations in loops
- APIs without cache and pagination
- infinite loops that can ultimately lead to a global crash of your app
- use of humongous arrays and collections (you may have to chunk it)
- anti-patterns: too much synchronous communication, bad/missing caching strategies (e.g., the app constantly calls the backend)
You can read more about performance anti-patterns here.
It can be hard to find critical optimizations while micro-optimization techniques are quite easy to implement.
😇 Bullshit!
While it's a bit off-topic here, I often go back to that post.