Career / Full-Stack / Story / Node.js / ASP.NET / Spring Boot
From ASP.NET to Node.js: My 10-Year Stack Evolution
Twenty years of shipping production systems across ASP.NET, Java, and Node.js — what changed, what stayed the same, and how I pick a stack today.
|8 min read
Introduction
I graduated with a B.Sc. in Computer Science in 2004. By 2007 I had my first full-time engineering role, and somewhere between then and now I quietly stopped writing C# and started writing JavaScript on the server. This is the story of how that happened — and what I kept from each chapter.
I'm writing this from Malang, East Java, and most of my work over the last decade has been for Singapore clients. The stack changes; the discipline of shipping doesn't.
2004–2007: Lecturer detour
Right after graduation I freelanced as a lecturer at one of the state universities in Palangka Raya, Central Kalimantan. Three years of teaching computer fundamentals to undergraduates turned out to be the best preparation for engineering I never planned. Explaining a database normal form to a room of nineteen-year-olds forces you to actually understand it.
I also built small sites for local businesses on the side, mostly with Joomla and WordPress in the first month or two on a project. Nothing portfolio-worthy. But it kept my hands on a keyboard.
2007–2013: ASP.NET and the WebForms-to-MVC era
My first proper engineering job was at PT Magicsoft Asia Systems. The stack was ASP.NET, C#, and MSSQL — and the .NET runtime was somewhere around 2.0 when I joined. I don't remember the exact MVC version we landed on, only that the team migrated from WebForms to MVC at some point and the postback model started feeling old fast.
Two projects defined that period:
- Vanda Clinic Management System — a healthcare records and billing system. Patient records, appointment scheduling, prescription tracking, invoicing. Heavy MSSQL stored procedures, reports rendered server-side, the whole pre-AJAX experience.
- GApple Retail System — a retail system. POS, inventory, stock updates, multi-branch sync, end-of-day reports.
Both systems exposed services over REST first, then SOAP when a later project required it. The REST work was straightforward — JSON over HTTP, simple verbs, easy to debug. SOAP came in for a newer integration that demanded WSDL contracts, generated client proxies, and XML namespaces. Going from JSON-over-HTTP back to schema-first SOAP made the trade-offs of each style very concrete.
I wrote across every layer: schema design, stored procedures, business logic, ASPX/Razor views, and deployment to IIS on Windows servers. No CI/CD, no containers — you remoted into the box and copied the build output across.
What I learned in this period and never let go of: read the SQL, trust the indexes, log the queries. If a system was slow, the database was usually shouting and nobody was listening.
2013–2014: Java detour, Linux, and a karaoke prototype
I left Magicsoft for PT Sentra Komputindo. Their entire system was built in Visual Basic 6.0 and they had decided to migrate everything to Java on Linux. My deliverable was a karaoke system prototype — Java backend, MySQL database, running on Linux servers.
This year was short but pivotal:
- First time writing Java professionally
- First time treating Linux as a target platform, not a thing other teams managed
- First time leaving the Microsoft stack behind
The karaoke prototype was unglamorous, but the operating-system shift mattered. After thirteen years of IIS and Windows Server, suddenly I was tailing logs over SSH, writing init scripts, and learning that journalctl exists for a reason. That muscle memory came back when Node.js arrived.
2014–present: Node.js, FeathersJS, and the Singapore SaaS years
In 2014 I joined PT Multi Guna Gemilang, where I still work today. Most of our clients are in Singapore, and the project pipeline pulled me into JavaScript on the server.
The shift wasn't an epiphany — it was incremental:
- Raw
http— the first Node.js services I wrote were almost embarrassingly bare.require('http'), manual routing, JSON.parse on the request body. It worked, but it didn't scale to the team. - FeathersJS research — we needed something more structured for quick delivery. After evaluating Express, Sails, and Hapi, FeathersJS won. Service-oriented out of the box, real-time via Socket.io with no extra wiring, and hooks gave us a clean place to put auth, validation, and logging.
- Production wins — two FeathersJS systems we still maintain today:
- Enabling Village (SGEnable) — a community platform built for Singapore's hub for people with disabilities
- CDAS ePayment — the multi-tenant invoicing and auto-payment system for container depot operators
Once those two were in production and stable, FeathersJS became the default for client work that needed speed-to-market. Node.js stuck because of three things, in this order: shared language across frontend and backend, npm ecosystem, and fast iteration with the team we had.
I wrote about the CDAS architecture in Multi-Tenant SaaS Architecture if you want the deep dive.
2024: Java came back via Spring Boot
I thought I'd left Java behind in 2014. Then in 2024 we picked up a project with a regulatory constraint: the Singapore government required the application to be developed in Java. That project became the URA parking offense system.
The stack was Spring Boot, Vite for the frontend, MSSQL on Azure. Coming back to the JVM after a decade was less jarring than I expected — the language had matured, Spring Boot had killed most of the XML-config pain, and the deployment story on Azure was solid.
What surprised me was how much I liked it. After ten years of dependency-update churn in Node.js, Spring Boot's stability felt like a gift. You can leave a Spring Boot service running for two years and the upgrade path is mostly painless. Try that with a Node.js LTS chain and you'll be debugging breaking changes every other quarter.
How I pick a stack today
Now I run multiple stacks side-by-side and pick per project:
- Java / Spring Boot — when the client wants long-term stability, strict typing matters, or there's a regulatory or enterprise constraint. Less frequent dependency churn, easier handover to enterprise ops teams. My default for "this needs to run for five years."
- Node.js / FeathersJS or Express — when speed-to-market is the priority, when the team is JavaScript-fluent, or when real-time features make Node.js the obvious fit. My default for SaaS MVPs.
- Python / FastAPI — mostly for personal projects and learning. I've experimented with Flask in the past but settled on FastAPI when I want to ship something quickly outside client work. Async, type hints, auto-generated OpenAPI docs — it hits the same sweet spot FeathersJS does, just in Python.
The honest answer to "which one is best": the one your team can ship and maintain. I've seen great Java codebases and terrible ones. Same for Node.js. The stack is a smaller variable than the discipline around it.
What stayed constant across all three eras
Twenty years in, the things that survived every stack switch are mostly not about the stack:
- SQL fundamentals — relational thinking, indexes, EXPLAIN plans. Still the most leveraged skill I have.
- API design — whether it's SOAP, REST, or GraphQL, you're still defining contracts between systems and thinking about idempotency, versioning, and error semantics.
- Logs over guesses — every production bug I've fixed in the last twenty years came down to reading logs carefully, not getting clever.
- Read the database — the database is usually right and you are usually wrong about what it's doing.
The frameworks rotate. The fundamentals don't.
Closing
If you're early in your career and worried that the stack you're learning will be obsolete in five years — it probably will be, partially. But the pieces that matter (SQL, API contracts, debugging discipline) compound across every transition. Pick the stack your team needs to ship, and put the time you save into getting better at the layer underneath it.
If you're hiring for a remote senior engineer who's done this transition a few times, I'm available — feel free to reach out.
Written by Erik Yuntantyo·Software Engineer·About me