Yashveer Singh
Connect
<- All posts
Founder Decision Frameworks12 min read

The Decision to Switch Tech Stack

Switching tech stacks means rewriting significant portions of the application in a different programming language, framework, or architectural pattern. It is one of the most expensive engineering decisions a company can make and one of the most frequently rationalized. The cases where it is genuinely necessary are fewer than most engineers believe. The cases where it is used to avoid fixing structural problems in the existing codebase are more common.

Written by Yashveer Singh, founder of Yashveer Labs.

What you actually need to know

  • The rewrite will take twice as long as estimated and cost twice as much in engineering capacity. Plan for this.
  • Most stack-related problems are solvable within the existing stack with refactoring. Exhaust this path before committing to a rewrite.
  • The strangler fig pattern is almost always better than a big-bang rewrite. Migrate incrementally.
  • Hiring constraints are the most legitimate driver for a stack switch. If you cannot hire engineers for the current stack, you cannot maintain it.
  • The new stack will have its own problems. The grass is not greener.
Migration ApproachRiskTimelineRecommended For
Big-bang rewriteVery high12 to 24 monthsAlmost never
Strangler figMedium12 to 36 monthsWhen incremental migration is possible
Parallel developmentHigh12 to 18 monthsWhen old stack is truly unmaintainable
Incremental refactorLowOngoingMost situations that seem to need a rewrite

The core argument

Joel Spolsky wrote about this twenty years ago in his essay on the second-system effect. The old code is not necessarily bad. It is the accumulated decisions of engineers who were solving real problems with incomplete information. Some of those decisions look wrong in hindsight. Most of them were reasonable given what was known at the time. The new team that looks at the old code and says "let's rewrite this properly" is overestimating their own foresight and underestimating the implicit knowledge embedded in the code they are proposing to throw away.

That said, stack switches sometimes are the right call. When the hiring pool for a language is genuinely constrained, when a technical limitation is genuinely preventing a product requirement, or when the maintenance burden is measurably unsustainable, the migration can be justified.

The question to ask before committing to any rewrite is: what specific, measurable problem will the new stack solve that cannot be solved within the current one? If the answer requires specific metrics (we cannot hire engineers for this language in this market, we cannot build this specific performance requirement in this framework), the decision is on solid ground. If the answer is qualitative (the code is messy, the framework is outdated, the team wants to use modern tools), the decision is on weak ground.

I have worked in enough codebases to know that the perceived problems with a tech stack are often really problems with the architecture decisions made in that stack, not with the stack itself. A poorly structured Node.js application does not become a well-structured Go application if the same architectural decisions are replicated in the new language. The discipline that makes the new stack better is the same discipline that could have improved the old one.

The legitimate drivers for a stack switch

Hiring constraint. When the current language or framework has a small and shrinking pool of practitioners, and the company's hiring needs exceed what that pool can supply. PHP, classic ASP, and older Ruby on Rails versions have created real hiring challenges for teams in specific markets. If the next five engineering hires the company needs do not exist in the local market for the current stack, the migration becomes a business necessity.

Performance limit. When the current stack genuinely cannot deliver the performance requirements of the product and the limitation is in the language runtime or framework architecture, not in the application code. This is rare. Most performance problems are in the application code (unoptimized queries, unnecessary network calls, missing caching) and can be fixed without a stack switch.

Technical debt beyond the point of return. When the current codebase has accumulated so much technical debt that incremental improvements are slower than a rewrite. This threshold is higher than most teams believe. A codebase with significant technical debt can usually be improved incrementally in less time than a full rewrite.

The strangler fig approach

The safest way to migrate a tech stack is incrementally, using the strangler fig pattern. New features are built in the new stack. Old features are replaced in the new stack as they need to be changed anyway. The old application shrinks over time as the new one grows.

This approach has three advantages: it validates the new stack in production before full commitment, it keeps the existing application running while the migration proceeds, and it allows the team to learn the new stack's patterns on non-critical features before applying them to the critical ones.

The disadvantage is that running two stacks simultaneously creates complexity: two deployment pipelines, two sets of dependencies, two monitoring configurations. This complexity is manageable for most teams and is substantially lower risk than a big-bang rewrite.

Common mistakes teams make with stack switches

  1. Starting the rewrite without completing the feature parity checklist. The old application has features the team has forgotten about. Starting the rewrite reveals this, but discovering undocumented features during a rewrite is expensive.
  2. Maintaining both stacks simultaneously for too long. The strangler fig approach requires a commitment to actually strangle the old code. Teams that run parallel stacks indefinitely double their maintenance burden without ever completing the migration.
  3. Not involving the team in the decision. The engineers who will do the migration need to agree that it is worth doing. A team that does not believe in the migration will not execute it well.
  4. Changing the database schema during the stack migration. Separating schema changes from the language migration reduces the risk surface significantly.
  5. Treating the rewrite as a clean slate for everything. A rewrite is a migration, not a redesign. The product requirements, data model, and business logic all carry over. Treating it as a redesign produces a second-system effect: the new system is more complex and less reliable than the old one.

Where to start: a 3-step stack switch decision

Step 1: Quantify the specific problem the switch would solve. Time spent on stack-specific maintenance per week. Number of positions that cannot be filled because of the current stack. Specific product requirements that cannot be built in the current framework. If the quantification is hard, the problem may not be as severe as it appears.

Step 2: Evaluate the incremental refactor alternative. For the specific problems identified, what is the cost of addressing them within the current stack? A three-month refactoring initiative that eliminates the most painful parts of the existing code is often more efficient than an 18-month rewrite.

Step 3: If proceeding, choose the strangler fig approach and define the first service to migrate. Start with a non-critical service that receives production traffic. Run it in the new stack for 60 days. Validate that the operational experience (deployment, monitoring, debugging) works as expected before committing to the full migration.

The Context in Which I Make This Judgment

Yashveer Singh. Founder of Yashveer Labs. The stack decisions I make for my own projects and for clients are deliberate. I use TypeScript on Next.js for frontend and API work, PostgreSQL for relational data, and reach for specialized tools only when the primary stack cannot solve the problem. I have inherited codebases that needed refactoring, not rewriting, and I have done the refactoring. If you are evaluating a stack switch and want a technical perspective on whether the current stack's problems can be addressed without migration, that is a specific evaluation I can do.

Related reading

FAQ

Frequently asked

Author

My approach to this kind of work

I approach this kind of work the way I would want someone to approach a system I depended on. With care, with rigor, with a sense that the next person who touches it should be able to understand it without my help. Yashveer Singh, founder of Yashveer Labs. That is the standard. If it is the standard you are looking for, I am the engineer to hire.

Related reading