Skip to content
Kien

Full-stack was not a choice

· 4 min read

Four and a half years across backend, frontend and deployment — not as a badge, but because internal tools have no other engineer. What each side of the stack taught the other, what the breadth honestly costs, and why the person who can follow a request from a React table to a supplier's SOAP endpoint is the person who can find where it broke.

  • full-stack
  • internal tools
  • devops
  • career
On this page
  1. The dashboard is the fastest API review you will ever get
  2. Shipping teaches you which config is real
  3. Operating teaches you that rollback is a feature
  4. The honest cost
  5. Why it matters on an integration platform

"Full-stack" reads like a choice on a CV, a deliberate positioning. Mine was not. For four and a half years the systems I worked on — internal business tools, admin panels, integration services — had exactly one engineer attached to them at a time, and that engineer was me. There was no frontend colleague to hand the dashboard to and no ops team to hand the deploy to. The stack was not something I spanned. It was something nobody else was standing on.

That constraint turned out to teach things that a specialised seat would not have, and it charged for them too. Both halves of that are worth writing down.

The dashboard is the fastest API review you will ever get

The purest lesson came from building an admin dashboard that consumed my own API. Not a colleague's API, where politeness buffers the feedback — mine, where every design shortcut arrived back on my own desk within the hour.

Pagination stops being abstract the moment you render the table. Error shapes stop being abstract the moment you have to show a human why their action failed, and discover your API returns three different failure formats depending on which layer threw. Empty states stop being abstract when the first real screen is a customer with no data yet, and the endpoint's answer to "nothing here" is indistinguishable from "something broke".

Every one of those is invisible from inside the backend. The API looked done. The contract had all its fields. It took consuming it — one React table, one TanStack Query hook, one afternoon — to find out what "done" had been hiding. I have reviewed APIs on paper since, and I still trust one screen of real consumption over any amount of reading.

Shipping teaches you which config is real

The reverse lesson ran frontend-to-backend. Designing a service, I used to treat configuration as generosity: make everything a setting, someone might need it. Deploying and operating that same service cured me. Config splits into two very different species — the values someone actually changes under pressure at an odd hour, and the values that were configurable because making them configurable felt rigorous. The second kind is not flexibility. It is surface area: more ways for two environments to differ, more places for a wrong value to hide. Only operating the thing tells you which is which, because only operations shows you which knobs ever get turned.

Operating teaches you that rollback is a feature

The deployment side — Docker, Kubernetes, Helm, Rancher, PM2, GitLab CI — taught the bluntest lesson: rollback is a feature you build before you need it. Our pipelines are manual by design; a human presses the button, and production asks for explicit confirmation before it runs. Every push bumps a patch version. That last habit sounds like bookkeeping until the first bad deploy, when "roll back" is only a real instruction if "back to what" has an exact answer. A version number per push means it always does.

None of that machinery gets built the week you need it. It gets built earlier, by whoever has stood on the operations side of their own deploy and remembers what it feels like when the answer to "what is running right now" is a shrug.

The honest cost

Breadth is not depth, and pretending otherwise is how full-stack becomes a euphemism. There are areas where I know enough to build the thing and enough to know a specialist would build it better: deep database performance work beyond the indexes and query shapes I can reason about myself; frontend accessibility and animation done properly rather than adequately; security beyond the standard hygiene; the Kubernetes internals below the layer I operate. I keep that list current on purpose. The way to keep breadth honest is to be able to say, without being cornered into it, which parts you would hand to a specialist — and to have actually asked for one when the stakes justified it.

Why it matters on an integration platform

The real payoff is specific to the kind of system I work on now. An integration platform is a chain: a React table fires a search, a queue fans it out to workers, a worker maps the request into whatever a supplier speaks — JSON if you are lucky, SOAP with an XML body if you are not — and the answer walks the whole chain back.

When that chain breaks, the failure almost never announces which link it broke in. The symptom surfaces at one end and the cause lives at the other. The person who can follow the request the whole way — who has written the frontend table, the queue consumer, and the XML mapping, and has deployed all three — is the person who can find where it broke, because no boundary on that path is a wall to them.

I would not prescribe this path; it was assigned, not chosen, and it cost depth I sometimes miss. But on a system whose whole job is crossing boundaries, having crossed them all at least once is not a badge. It is the debugging toolkit.

Related posts

· 5 min read

The dashboard that consumes your own API is the fastest API review available, and the specifics are what teach: a table whose identity row carries dozens of supplier-ID columns, three different reasons a screen can be empty, an error code that has to become a sentence someone can act on, and a money screen that must say which number is shown and which is charged. Plus the half nobody plans for — an internal tool is a production system with users who sit near you.

  • internal tools
  • API design
  • frontend
  • operations