About this article
This article is the fifth deep dive in the “Software Architecture” category of the Architecture Crash Course for the Generative-AI Era series, covering framework selection.
As the obsolescence history of AngularJS, Backbone.js, Struts, and Silverlight demonstrates, FW selection determines the next 5 years of hiring market and technical debt simultaneously — the heaviest move after language selection. The article compares major FWs per language and covers use-case selection, LTS management, vulnerability response, and AI-era generation accuracy.
Before you read this
This article is mostly about development: programs and APIs. If IT vocabulary is unfamiliar, reading the primer "Programs and APIs" first makes it far easier to follow. You can also look anything up in the glossary as you read.
What is a framework in the first place
A framework is “a skeleton and common-parts kit for building an app.”
Imagine a plastic-model kit. Parts (libraries) can be bought separately, but the skeletal frame (framework) can’t be swapped for another brand mid-build. Frameworks like Spring Boot, Next.js, Rails, and FastAPI come pre-equipped with “mechanisms every app needs” — routing, DB connections, authentication — so developers just place business logic on top of that skeleton.
Why framework selection matters
What happens if you pick the wrong framework? Swapping out the skeleton is essentially a rebuild. Netscape’s 1998 browser code rewrite that lost the browser wars symbolizes the weight of FW migration.
FW selection simultaneously determines the talent base, future viability, and library ecosystem you’ll work with — once decided, you live with it for years. Library = part, framework = skeleton. The skeleton can’t be changed later.
Once language is settled, picking the mainstream framework for that language is the basis. FW selection decides hiring base, future viability, and library ecosystem simultaneously — once chosen, you live with it for years.
Library = “part.” Framework = “skeleton.” Understanding this difference matters. Libraries can be swapped later; replacing the skeleton is essentially a rebuild. Netscape’s 1998 code rewrite that lost the browser wars symbolizes the weight of FW migration.
Library = part. Framework = skeleton. The skeleton can’t be changed later.
The axes that actually decide it are these.
FW selection isn’t a single metric like “fast” or “light”; evaluate jointly across multiple axes. Especially with long-term operation, talent-market depth and LTS presence are decisive.
| Axis | Substance |
|---|---|
| Maturity | Track-record length, stability, LTS (long-term support) presence |
| Ecosystem | Surrounding-library / plugin breadth |
| Performance | Throughput, startup, memory |
| Learning cost | Documentation and information volume |
| Adoption cases | Hiring ease, job-market breadth |
| Dev speed | scaffold and convention richness |
Performance can be optimized later, but talent shortage shortens project lifespan.
The major frameworks by language
Java and C# — the two enterprise standards
Java FWs feature overwhelming track record, especially in large-enterprise business systems. Spring Boot is the de facto for enterprise — surrounding libraries are abundant, and information density is rich.
Java’s Spring dominance accumulated over 20+ years covering DI, AOP (Aspect-Oriented Programming — a way to inject cross-cutting concerns like logging and transactions), security, batch, messaging — meeting business requirements head-on. The ecosystem has overwhelming case examples in banking, insurance, public sector, with no shortage of precedents.
| FW | Trait |
|---|---|
| Spring Boot | De facto. Enterprise-business standard |
| Micronaut | Compile-time DI (Dependency Injection — injecting dependent objects from outside) / fast startup |
| Quarkus | GraalVM-aware / cloud-native oriented |
| Ktor (Kotlin) | Lightweight, modern, async; written in Kotlin |
For finance, public sector, and large-enterprise business systems, Spring Boot only.
C# and .NET occupy the same slot on the Microsoft side.
Microsoft’s official FW family pairs performance and productivity well. ASP.NET Core specifically is cross-platform and high-performance, scoring alongside Node.js and Go in benchmarks. Strong Azure integration and a first choice in companies with substantial Windows assets.
For C#, Microsoft official FWs (ASP.NET Core) are the only mainstream; the language, FW, IDE (Visual Studio), and cloud (Azure) are consistently provided by one vendor — the biggest trait. Version upgrades are managed by Microsoft directly with few compatibility issues, and the long-term operation of large enterprise business systems has good chemistry.
| FW | Trait |
|---|---|
| ASP.NET Core | .NET official; high-performance, cross-platform |
| Minimal API | Lightweight API definition inside ASP.NET Core |
| Blazor | Build SPAs in C# alone (WebAssembly) |
Fits: many Windows / Azure assets / large-scale business / Unity integration.
In environments leveraging Microsoft assets and Azure, this is an overwhelmingly strong FW family.
TypeScript and Node.js — the pick for new web work
Node.js’s hallmark is “too many choices.” From the elder Express to type-friendly Fastify, well-DI’d NestJS, edge-runtime-aware Hono — pick by use. Frontend-integrated Next.js / Nuxt / SvelteKit configurations that “co-host APIs” are increasing.
The Node.js ecosystem’s FW proliferation is driven by JavaScript’s openness and npm’s explosive scale. No single decisive FW emerges; instead you have flexibility to pick the optimum per use, and “unifying frontend and backend in one language (TypeScript)” is a strong AI-era benefit.
| FW | Trait |
|---|---|
| Express | Eldest, most adopted. Thin and free |
| Fastify | Fast, type-friendly, fast JSON |
| NestJS | DI, structured. Angular-like writing. Good for large scale |
| Hono | Edge-runtime-aware, lightweight, TypeScript-first |
Frontend-integrated: Next.js (React) / Nuxt (Vue) / SvelteKit — co-hosting SSR and APIs.
For TypeScript, NestJS (structure focus) or Hono (lightweight, edge). Express is rarely worth picking for new builds today.
Python — cleanly divided by purpose
Python FWs split clearly by use. New APIs: FastAPI. Full-stack with admin: Django. Free-form: Flask — that split is settled.
Python’s FW split exists because the language spans AI, data, web, scripting, with different functional needs per area. FastAPI especially fits AI / ML API wrappers via type hints + OpenAPI generation; many Python-selection rationales now lean on AI integration.
| FW | Trait |
|---|---|
| Django | Full-stack with admin. Internal tools etc. |
| FastAPI | Type-hint-driven, async, OpenAPI auto-generation |
| Flask | Micro-FW, free, small-scale |
- New API: FastAPI (type safety + performance).
- Want admin pages: Django.
- AI-API wrapper: FastAPI (direct Python-asset integration).
If you pick Python for AI integration, FastAPI is essentially correct.
Go and Rust — thin and fast
Go’s FWs are thin because the language itself is simple. The standard library net/http covers a lot of scale, and the “FW-light, standard-library-centered” style is common.
Go culture doesn’t welcome heavy FWs; explicit code is virtuous. The result: thin routers like Gin / Echo combined with the standard library — Docker and Kubernetes codebases are written in this style.
| FW | Trait |
|---|---|
Standard net/http | Often sufficient with official packages alone |
| Gin | Lightweight, fast, rich middleware. Most adopted |
| Echo | Same family as Gin; API-oriented |
| Chi | Faithful to net/http; small, clean |
For Go, thin router + standard library is the canonical path; overwhelming track record in microservices and cloud-native infrastructure.
Rust sits at the extreme end of the same axis.
Rust FWs shine where extreme performance and memory safety are needed. Learning cost is high; picking Rust where C# or Go would suffice sacrifices development speed. Adoption is realistic only when performance is truly necessary.
Rust web FWs have coalesced around the tokio async runtime with Axum effectively becoming the mainstream. The ecosystem is still developing; no all-in-one FW like Spring or Rails. Rust style is combining small crates (libraries).
| FW | Trait |
|---|---|
| Axum | tokio-official lineage; type-driven and easy to write |
| Actix-web | High performance, mature; consistently top in benchmarks |
| Rocket | Ergonomics-focused; writeability priority |
Fits: extreme performance / memory safety as absolute requirement / edge computing / small distributable binaries.
For new builds, Axum first. Actix-web for maturity, Rocket for writeability.
PHP and Ruby — fastest MVP, and existing assets
PHP first.
PHP FWs are “Laravel-dominated.” scaffold, ORM, auth, queues all bundled with mature documentation; the learning curve is gentle. The legacy maintenance pile is huge, so the talent market persists.
| FW | Trait |
|---|---|
| Laravel | Most adopted / fast dev / rich docs |
| Symfony | Robust, large-scale-oriented, enterprise-friendly |
| CakePHP | Convention-focused, persistent adoption in Japan |
For WordPress projects and small/mid business apps, Laravel only. New adoption is decreasing.
Then Ruby.
Ruby’s FW situation is essentially Ruby on Rails. The originator of “convention > configuration”; the dev experience of one scaffold command auto-generating features still beats other languages. But Rails itself is heavy with poor FaaS / microservices fit, so adoption skews toward startup MVPs.
| FW | Trait |
|---|---|
| Ruby on Rails | Originator of “convention > configuration”; fastest MVP |
| Sinatra | Micro-FW. Small or partial use |
| Hanami | Modern, clean-architecture-oriented |
Still primary for “fastest startup prototype.”
How to choose — by use case and LTS
| Case | Recommended |
|---|---|
| Large enterprise business | Spring Boot / ASP.NET Core |
| High-speed API / AI integration | FastAPI / Fastify / Axum |
| Startup MVP | Ruby on Rails / Laravel / Next.js |
| Microservices | Go (Gin/Chi) / gRPC |
| Full-stack JS | Next.js / Nuxt / SvelteKit |
| Extreme performance / embedded | Rust (Axum / Actix-web) |
| Internal business tools (admin needed) | Django |
Language and FW selection go together as the rule; deciding language and “FW later” is a recipe for failure.
Which framework fits which use lines up as follows.
Locking “this for this use” in numbers speeds judgment. Practical mapping as of April 2026:
| Use | Team size | First-choice FW | LTS period | Hiring difficulty |
|---|---|---|---|---|
| Large enterprise business | 30+ | Spring Boot (Java) | 3-5 yr | Low |
| Large .NET business | 30+ | ASP.NET Core (C#) | 3 yr | Mid |
| New web SaaS / B2C | 5-30 | Next.js (TS) | annual major | Low |
| New API-centric web | 3-30 | NestJS (TS) / FastAPI (Python) | 1 yr | Mid |
| Startup MVP | 1-5 | Rails / Laravel / Next.js | LTS available | Low |
| Microservices (internal) | 10+ | Go + Gin / gRPC | 1 yr | Mid-high |
| Edge computing | 1-10 | Hono (TS + Edge) | New | Mid |
| Admin-screen-centric | 1-5 | Django (Python) | 3 yr | Low |
FW major upgrades happen “every 1-3 years”; picking non-LTS produces yearly migration work. Spring Boot, Django, Rails, Laravel are LTS-explicit; business systems should pick LTS only. FWs with “chase the latest” culture like Next.js assume yearly major-version response.
Don’t run non-LTS versions in production. Every year becomes a migration project.
Three scenarios
If you are building solo or at a startup
Next.js in TypeScript, or Rails or Laravel if you prefer the server-side-integrated style, is the shortest path. Convention-based full-stack frameworks give high AI generation accuracy, and the fact that there is less for you to decide is what lets you concentrate on the product itself.
If you are a small or mid-size SaaS
Next.js for the web layer, and NestJS (TypeScript) or FastAPI (Python) where the work is API-centric. Note, though, that a framework with a culture of chasing the latest — Next.js being the obvious example — assumes you have the capacity to handle a major version every year. Build that following cost into the team’s plan.
If you are a large enterprise
Spring Boot or ASP.NET Core — something that states an LTS explicitly — is the only real choice. A framework major version lands every one to three years, so choosing outside LTS turns every year into a migration project. With ten-year operation and hiring as the priorities, staying with the boring choice is the correct answer.
AI decision axes — Does the AI know that framework well?
AI generation accuracy tracks how mainstream the framework is.
Once AI-driven development becomes the norm, “how well does AI know this framework” becomes a decisive factor in FW selection. This isn’t just about volume of information — there’s a feedback loop: mainstream FW → more training data → higher AI generation accuracy → more developers gather → even more information. Minor FWs can’t enter this loop, so the gap with mainstream will only widen.
Convention-based FWs and AI generation compatibility
The AI-era development workflow is shifting to “AI scaffolds/generates initial code → humans review and fix.” Here, convention-based FWs (Rails, Next.js App Router, NestJS, etc.) have the advantage:
- AI output is predictable — it generates according to conventions, so reviewers who know “the correct pattern” only need to check the diff
- File placement is predetermined — AI doesn’t hesitate on “where to put what,” keeping project structure intact
- Cognitive load decreases across the team — AI-generated code and human-written code share the same structure, so you can review without worrying about “who (or what) wrote this”
Conversely, with high-freedom FWs (Express, Flask, etc.), the structure of AI output changes every time depending on prompts and context. Review costs don’t decrease, leading to “we introduced AI but development speed didn’t change” situations.
FW migration cost doesn’t decrease even with AI
Some expect “AI will let us switch FWs later,” but this isn’t realistic. AI excels at file-level code conversion, but the essential difficulty of FW migration lies in “differences in implicit assumptions.” Routing conventions, middleware execution order, DI container lifecycles, error-handling philosophy — these differ per FW, and AI still cannot complete a migration while maintaining overall consistency.
Therefore FW selection irreversibility hasn’t changed in the AI era. Rather, if you pick a FW with high AI generation accuracy from the start, it compounds over 5 years of development velocity — making initial selection more important than ever.
The AI-related checkpoints for framework selection come down to this.
| Aspect | What to verify | Example |
|---|---|---|
| Reviewability of AI-generated code | Can you tell at a glance whether generated code follows conventions? | Next.js App Router: directory structure = routing, so deviations are immediately obvious |
| Ease of prompt instructions | Can you convey FW conventions concisely in a system prompt? | NestJS: Module/Controller/Service 3-layer is clear and easy to instruct |
| AI review tool integration | Can you embed AI review / AI test generation in CI/CD? | Do GitHub Copilot / Coderabbit etc. understand the FW’s test conventions? |
| Upgrade automation | Can codemods / migration CLIs run alongside AI? | Next.js: official codemod provided. Rails: rails app:update is standard |
Pitfalls and forbidden moves
Serious injury comes from three directions: people, vulnerabilities and migration. Here are the six most dangerous.
| Forbidden move | Why it is bad → what to do instead |
|---|---|
| Adopting a sharp new framework for business work | engineers do not come and the project freezes → stay with mainstream plus LTS |
| Running a non-LTS version in production | a major migration lands every year → choose one that states an LTS explicitly |
| Leaving vulnerability patches unapplied | Equifax 2017 left a Struts 2 patch for two months and leaked 147 million records → set an SLA of 72 hours for critical |
| No update strategy for dependencies | an event like Log4Shell hits you directly → run automatic pull requests with Dependabot |
| Reaching deep into the framework’s internals | a major update breaks compatibility and multiplies the migration cost tenfold → use only the official extension points |
| Leaving a version upgrade for three years or more | catching up in one jump becomes impossible and it is effectively a rewrite → follow the annual cadence |
Adopting a framework is “a contract to keep maintaining it.” Setting a patch SLA (critical within 72 hours, high within a week, medium within a month) and running automatic pull requests with Dependabot is the modern standard.
Author’s note — Equifax and the Struts nobody patched
The Equifax 2017 incident — leaving an Apache Struts 2 known-vulnerability patch for two months, leaking 147M people’s records — confronts the industry with the link between FW selection and patch operation (full details in Appendix: Major Incident Catalog).
Few developers haven’t sweated over delaying a patch. “Big release next week, after that” thinking and then in-week internal scans flagging Critical, forcing emergency maintenance — common stories.
Adopting a FW and then “installing-and-done” can turn into a fatal hit during the weeks between vulnerability disclosure and application. Pick LTS-marked versions, build a routine for following security info — these aren’t “do later”; decide them at selection time.
FW adoption is a continuous-maintenance commitment; embed continuous-maintenance capacity into design from adoption.
What you must decide — what’s your project’s answer?
Articulate your project’s answer in 1-2 sentences for each:
- Framework adopted (main + surrounding libraries)
- LTS version or latest
- ORM / DB-access library
- Auth library (in-house or external service)
- Test framework
- Future version-upgrade strategy
Write your answers down as an ADR. A concrete guide to writing them is here.
Related Articles
Summary
This article covered framework selection — major FWs per language, LTS management, vulnerability response, and AI-era generation accuracy.
Enterprise: Spring Boot. New web: Next.js. Python: FastAPI / Django. Cloud-native: Go + Gin. LTS mandatory, conventions preferred, lean on AI-known mainstream FWs — the realistic answer.
The next article covers transaction design (ACID / eventual consistency / Saga / Outbox).
Back to series TOC -> ‘Architecture Crash Course for the Generative-AI Era’: How to Read This Book
I hope you’ll read the next article as well.
Also popular with readers
📚 Series: Architecture Crash Course for the Generative-AI Era (28/95)