Full-stack: end of honeymoon
Tags: fullstack, programming, frontend, backend
Published: 2023-02-26 20:25:16

With the ever-growing popularity of `full-stack engineering` it is time to give some thoughtful critique to the hype around it - at least to lower expectations back to realistic levels.

First let's start with an analogy!

## The full-stack doctor at the most productive hospital
Imagine you have been experiencing double vision for weeks, and your anxiety grows when the MRI confirms that you have a benign growth in your brain that must be removed. The local hospital where your surgery will take place boasts about its productivity, claiming to have served many patients with few staff members. You meet your surgeon, who explains what they mean by "full-stack doctors":

> Back in the day, when the anesthesiologist was on vacation, we could not do surgeries, or when the nurses got sick. Now we only hire doctors who do everything by themselves - no room for bottleneck people!

You ask if they have considered hiring a second anesthesiologist, but the doctor does not even hear you and continues:

> While brain surgery is not my primary area of expertise, I am fairly confident that with our recent tools, I will excel at it! I have also just consulted DoctorGPT, the AI surgeon, and it gave me excellent tips.

At this point your heart-rate goes through the roof.

## Language Fragmentation
Let's say you use `Java` for backend and `JS` for frontend.  You immediately fire up a `class` in JS and implement the good ole **Strategy Pattern**. You are proud of yourself, but "oh, no!", you could have solved the problem with a simple pure function you can totally write in `JS`.

And this is not the only problem when you have language fragmentation: each has wildly different ecosystems, different ways of dealing packages/modules, each has wildly different coding philosophy: should you use object-oriented programming or should you use functional programming (light - real FP in JS is quite painful; the language was neither designed for OOP nor for FP)?

IDEs, debugging tools, CLI tools, setup etc. are all going to be very different from each other. Basically, if you have 2 languages you have to be up-to-date with twice as many of these as if you were focusing only on one language.

You might know my pain if you ever tried to install a _different_ version of `python` compared to the "fire and forget" `nodejs` installation.

## The elements in a stack are not just programming languages
Even with the same language you will have problem with libraries, platforms and frameworks. Each element in the stack is different and have its very own gotchas. Browser and backend server have very different limitations for example.

Here's another analogy: imagine someone hands you an alien spaceship with a robot to assist you. The robot tells you how to operate the controls and with that knowledge you successfully do a New York-Tokyo trip in just 30 minutes. You are blown away. Then the damn spaceship slows down. The robot tells you to "_simply change the old antimatter to new one_".

However, you have no idea how to service the spaceship, obtain anti-matter, or dispose of the old one. The easy abstractions ended there for you, and you realize how much you don't know.

Returning to backend coding, you're not just writing features in, say, Javascript, but you also have to deal with a lot of issues that only happen on the backend, such as:

- Memory-leaky code that worked perfectly in browser sessions now creates random "Out of memory" crashes and restarts every second, causing inconsistent data in the database.
- As you try to fix the issue, you realize that **backend memory forensics** is a beast on its own, and the tools you _were familiar with on the frontend_ are not helpful. You have to learn new tools and paradigms.
- While investigating how to mitigate the data inconsistency issues, you realize that skipping proper SQL learning and going with `Prisma` or another **ORM** now bites you. Since you don't know you need transactions, you don't even know how to search for it.

Okay, you might say, of course, everybody knows about transactions, and I'm just catastrophizing. Yes, here, I think I have sacrificed some realism to keep this article short and memorable.

## Scaling of a product shows blind spots
There is a point when **naive ORM-based queries** are just not performant enough and the costs and waiting times skyrocket. There is a point when people complain about how slowly your frontend loads because of the size of a badly architected `CSS` bundle. There is a point when you don't even know you've been hacked until you read about it in the news because you thought _"the library we used was safe"_.

> The most dangerous aspect of `full-stack engineering` is giving **false confidence** that by being able to write business logic on both frontend and backend you are _actually_ both a frontend and a backend developer.

Let's say you have 3 responsibilities as a `full-stack developer`: creating UI code in `TypeScript/CSS`, writing backend code in `Java` and security. You only do all of these part-time (while you are working on the frontend you don't work on backend), and now you have to split your learning time among 3 responsibilities, not one. Compare it to a hacker who only focuses on how to penetrate systems, full-time, and nothing else.

> The **more responsibilities** your tech stack have the **less capable** you are going to be to tackle them. 

Even with a really great **ORM** like `Prisma` that hide a lot of the underlying complexity you will arrive to real world problems where you are better off writing a complex raw `SQL` query to minimize the number of turnarounds. Or we also had multiple cases where we had to write very custom `SQL` as part of the _"automated migration"_.

> Every one item in your stack has slightly or wildly different programming paradigms. The abstractions provided by great libraries eventually run out juice at one point and then you are either _a master of each domain's paradigm_ or you will run into problems. 

As a summary I encourage you, the reader, to think about all the platform-specific gotchas you ran into, the ones that made you stop your work for days or week.

It is our responsibility to set realistic goals to ourselves and to our managers. Hiring or organizational problems cannot be solved by pushing all responsibilities to the developers at hand.