Existence of V1 (the very first version of our solution) actually shows our hope that one day we will be “allowed” to be working on V2!

Tech debt


There are ugly parts, we know, we deliver something quickly under pressure – but it works (for now). Most of us don’t “see” them. It is usually because of lack of sufficient experience in the field.

Most managers don’t “understand” technology; never mind the technical debt!

If they are not willing to give us time, we have to (sneakily) over-estimate the new features requested in order to be able to resolve technical debt gradually. In the worst case, we may be required to shut the “business” for maintenance!

Don’t be naive!

Long time ago, I caught a “naive” looking SQL bug in a system I was working on:

FROM [a-table]
WHERE id IN (...[parameters])

When I printed it on a MS Word document, the team was shocked: it was over 100 pages long! The query was over 2MBs. MySQL server was not happy: it rejected the query because it was configured to reject payloads over 2MB!

Once I crashed a MySQL server when I tried to add a column to a table!

ALTER TABLE [a-table]
ADD COLUMN [a-column] VARCHAR(100);

In the past, MySQL server developers were also naive: they did not check the disk requirements of DDL commands before executing them.


Another time, a system we developed almost stopped working after I went on holiday! I had to spent 2 weeks in & out of an internet cafe trying to find and fix the issue. Firebird SQL database server struggled with the load when there were “many” records in a table. We were using triggers inefficiently! A trigger can work perfectly for a single row but it may not work as expected for many rows. We had to move the logic to the application server and optimise the business logic.

A database is usually the bottleneck in a classic 3-tier architecture: App, API, DB. Take advantage of using multiple API server instances and use their computational power.

Test, test, test! … and automate! … but moderate!

When a solution works for most of our test scenarios, it does not mean that it will work 100% of the time: one day it will need to handle a case that could happen 0.1% of the time.

It’s about considering moderation: we can not automate every task. We should keep an eye on upgrade operations – i.e. software releases in production environments.

Don’t be a fanatic!

We must see the imperfections of our stuff! We should know about the pros & cons (or limitations) of our solutions; the software libraries, frameworks, systems that we rely on. We should be able to talk about them without twitching!

GraphQL is the best way we can create an API these days.


  1. we can avoid over-fetching data
  2. we can avoid under-fetching data
  3. we can use type safety for inputs and outputs
  4. we can use code generation tools to scaffold code for App & API.
  5. server will use CPU, memory and network gracefully
  6. it is less “chattier” than REST or gRPC (as the App does not need to send many serial or parallel requests)
  7. it provides the best developer experience on client-side (as it hides the complexity of working with many microservices for instance)
  8. it leads to better user experience (as the network speed between user and servers is slower than the speed between the servers)
  9. we can send a batch of commands to the server



  • model relationships may actually lead to over-fetching data: beware of 1 + N queries which can be solved by batching the queries using a data loader library
  • some App developers may not actually try to retrieve only the data they need; so beware if you are deploying public GraphQL APIs and use a query complexity score calculator with a limit
  • some App developers may batch so many commands together and it may lead to huge input and output payloads – not graceful usage of CPU, memory and network neither on server-side nor on client-side! Limiting complexity score can help.
  • GraphQL (or REST, or even HTTP v1) is not designed to handle files – use a proper file server to exchange files; so GraphQL can easily refer to the file URLs – ideally using HTTP v2.
  • BTW, there is NO V1 in GraphQL world 😉

    Image from Unsplash: https://unsplash.com/photos/blue-and-white-wooden-house-on-green-grass-field-during-daytime-1UMrSoItdDE