maciej łebkowski
Maciej Łebkowski

Switching the tech stack

in Professional

This is a third installment of a 4-part series:

  1. Leaving Phone
  2. Changing teams
  3. Switching the tech stack 👈
  4. Learning NestJS

After more than 20 years of being primarily a PHP developer, I am finally changing the tech stack. I guess I won’t have to eat a chair after all. Actually, I am switching more than just languages: a new company, a new team, a new framework, new people around, a new business area, a new role… But you can read all about that in the previous chapters. Today, let’s focus on my first steps in adopting to — spoiler alert — NestJS ecosystem.

The goals

We’re trying to quickly bootstrap a relatively small/easy application to aid with our business goals. It’s familiar territory: we need to move fast, validate the idea, and iterate in response to feedback. So we can skip a lengthy planning phase and get right to the job.

Technology choice

My first thought was to build the MVP using something I’m familiar with, so PHP. The obvious upside was to bootstrap quickly, having a lot of experience with the tool and ecosystem around it. That was under the assumption that it is temporary, and would be rewritten after a couple of weeks. We all know how long temporary solutions last, so that was crossed out fairly quickly, especially since this language was not a part of the company’s stack.

Then the idea of python was brought up, but the justification was shortsighted. The app was in the general data area, so python seemed like a fit. But on a deep dive, it turns out that the problem is not complex enough to warrant a specialized tool to solve. That, and the team in general being unfavorable to introducing that language to the tech stack, resulted in abandoning that idea.

Two last candidates were on the table, both already used by the team: .NET or TypeScript. We had a discussion before about the state of existing applications, language capabilities, maturity, and enterprise features. This is why .NET was so appealing. A lot of plumbing would just work without me having to deal with it for too long (not unlike in Symfony): the dependency injection container, command buses, async messaging, advanced security and access control topics, reduced boilerplate, and much more. I know that I can have expectations that most of the common problems are already solved, so I could focus on what is important: the business logic.

Previously, at Docplanner, it was also used by other teams, but I never considered it, turning my attention to more flashy alternatives like Kotlin.


You might have an impression that the same is true for JavaScript, but it’s not quite the same. It’s easy to find an npm package for anything, the community is quite potent in that regard. Unfortunately you soon realize that it’s only surface level.

There is a lot of diversity in the ecosystem, but I don’t necessarily mean it in a good way. You need to rely on tons of plugins or packages, but they are not always homogeneous, and often have problems working together. Some are feature rich, others solve simple use cases. There are those that are opinionated and force their way of thinking on you, and others are more flexible and forgiving.

While this is less often seen nowadays, there are packages written in JavaScript without type definitions. That is mostly a deal breaker to use in a TypeScript codebase.

And in the end, since there are so many to choose from, so when you finally find a lib, you need to assess the risks of using it. What is the code quality? Will I be able to extend or otherwise modify it? Is there enough flexibility, or are we forcing ourselves into a corner? Is it still actively maintained?

Sidestory: A few years ago I wanted an OAuth2 interceptor for axios. I had a similar middleware for PHP’s Guzzle on the backend. I was expecting that given some basic configuration of secrets, endpoints and scopes, it would manage the token lifecycle, its persistence and attach the credentials to requests automatically. The most popular lib I found wasn’t doing any of that. As far as I can recall, it only injected a bearer token into headers, and even that was buggy. The logic that probably every other OAuth client uses, we had to implement ourselves. Long story short, that was not a pleasant experience.

The final decision

Forget the whole previous section. In the end, I decided to take the path of least resistance: NestJS, since I already knew TypeScript, and the framework was mature enough and had a bunch of enterprise features already.

In the next chapter I describe my first steps with the framework, some decisions I made along the way, great tools that really made a difference, as well as some shortcomings that I’m yet to overcome.

Was this interesting?

About the author

My name is Maciej Łebkowski. I’m a full stack software engineer, a writer, a leader, and I play board games in my spare time. I’m currently in charge of the technical side of a new project called Docplanner Phone.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. This means that you may use it for commercial purposes, adapt upon it, but you need to release it under the same license. In any case you must give credit to the original author of the work (Maciej Łebkowski), including a URI to the work.