One of the main reasons(there were quite a few) was not the outdated architecture itself — on the contrary, improving it was part of my role. The difficulty came from the way tasks were managed: assignments that were close to completion were taken away and reassigned to others without clear, technical, or performance-based justification. The team lead at some point made a comment - "you look tired" - which was not true.
In other cases, after optimizing processes - for example, passing data as strings instead of performing unnecessary serialization when objects were not involved, thereby removing serialization overhead - and adding additional security improvements, my solutions were rejected solely because, according to the team lead, they did not align with their outdated internal code.
But that was the intention, since the existing code introduced performance overhead and did not meet basic security requirements.
There were also situations where I proposed more efficient solutions, but they were rejected due to incorrect technical understandings, such as the claim that having lodash in package.json automatically means the entire library enters the bundle size—something that is not true. As a result, I was repeatedly pushed to ship slower, suboptimal solutions.
The team lead was not technically competent. He not only enforced low-performance implementations but did not listen when I raised concerns, and he did not benchmark, test, or analyze the solutions that were proposed.
Over time, it became clear that this behavior was systemic, there was a lack of desire for development and modernization, and I began to question what my real role in this team was and for what purpose I was brought in. Due to significant divergence in views on quality, architecture, and development, I judged that in another team I could be significantly more useful and effective.
Additionally, it became evident that the company lacked sufficiently experienced and stable senior technical staff. There was no dedicated technical team lead; instead, the role was effectively filled by a product owner who was not a technical professional and whose technical knowledge was minimal. Despite this, final technical decisions were expected to be made by this role, often resulting in non-competent choices that led to reduced productivity, weak security, and recurring bugs.
Furthermore, when technical explanations were provided, these were often disregarded - or possibly not fully understood. Rather than reviewing documentation, testing solutions, or seeking clarification, decisions were made and enforced directly, frequently without adequate technical justification.
The project had some specification, but it was underdeveloped and insufficient. It was not maintained or extended when new features or use cases were introduced, so it quickly became outdated and unreliable. There were effectively no diagrams - at most one high-level diagram - so architecture, APIs, and workflows lacked a clear visual reference. Without a living spec and adequate diagrams, onboarding, alignment, and consistent implementation suffered, and discussions often relied on assumptions or stale knowledge. Creating specification or documentation for the code one builds is a mark of senior development practice; that largely did not happen, so things remained often unclear. Double standards were common - some could do certain things while others were criticized for the same.
As a result, the client began raising concerns about the application’s slow performance and overall quality. Eventually, the client started onboarding additional developers independently, separate from the main team, to help address these issues. In this situation, the client’s actions were fully justified, as the work being delivered did not meet acceptable quality standards.