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.
What is a framework in the first place
A framework is, in a nutshell, “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.
Deciding the “app’s skeleton”
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.
Decision axes
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.
flowchart TB
FW([Candidate FW])
M[Maturity<br/>LTS presence]
E[Ecosystem<br/>Surrounding libraries]
A[Adoption cases<br/>Hiring market]
L[Learning cost<br/>Information density]
P[Performance]
S[Dev speed<br/>scaffold/conventions]
GO([Candidate that runs 5 years])
FW --> M --> GO
FW --> E --> GO
FW --> A --> GO
FW --> L --> GO
FW --> P --> GO
FW --> S --> GO
A -.|most important| HIGHLIGHT[Talent shortage<br/>shortens project<br/>lifespan]
classDef root fill:#fef3c7,stroke:#d97706;
classDef criteria fill:#dbeafe,stroke:#2563eb;
classDef important fill:#fee2e2,stroke:#dc2626;
classDef goal fill:#dcfce7,stroke:#16a34a;
class FW root;
class M,E,L,P,S criteria;
class A,HIGHLIGHT important;
class GO goal;
| 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.
Java / Kotlin
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# / .NET
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.
Python
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
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
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.
Node.js / TypeScript
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 (Server-Side Rendering — server builds HTML before returning) and APIs.
For TypeScript, NestJS (structure focus) or Hono (lightweight, edge). Express is rarely worth picking for new builds today.
PHP / Ruby
PHP
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.
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.”
Recommendations by case
| 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.
Framework × use ladder
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.
Framework selection / operation traps
| Forbidden move | Why |
|---|---|
| Adopt a niche emerging FW (SolidStart, Qwik) for production | Engineers don’t come; project freezes via hiring difficulty |
| Run non-LTS in production | Short support window; yearly major migrations |
| Keep using a deprecated FW like AngularJS | Official support ended January 2022; sites that couldn’t migrate had to rewrite |
| Leave critical patches 2+ weeks | Equifax 2017 left an Apache Struts 2 patch unpatched 2 months, leaking 147M people’s records. 72-hour Critical-patch SLA is the floor |
| Touch FW internals deeply | Major upgrades break compatibility; migration cost 10x |
| Switch FW mid-stream | Skeleton swap is essentially rebuild. Same fate as Netscape’s rewrite |
| No dependency-update strategy (no Dependabot) | Vulnerability notices missed; direct Log4Shell (Dec 2021) hit |
| Leave version updates 3+ years | Catching up is impossible; rewrite |
| Choosing a FW by performance benchmarks alone | Performance can be optimized later; talent and ecosystem depth affect project lifespan far more |
| Choosing a FW assuming mid-stream switch is possible | Skeleton swap is essentially rebuild; the first selection decides everything |
FW selection requires “design including continuous-maintenance capacity from adoption.” Set patch-application SLAs (Critical 72 hours, High 1 week, Medium 1 month) and automate PRs with Dependabot — modern standard.
FW adoption is “a contract for continuous maintenance.” Not “install and done”; weekly maintenance is the assumption.
AI decision axes
| AI-era favorable | AI-era unfavorable |
|---|---|
| Next.js / NestJS / FastAPI (mainstream, info-rich) | Minor / emerging frameworks |
| Spring Boot / Rails (mature, established patterns) | Custom in-house frameworks |
| Products with clear “the framework way” | Products without conventions, too free |
| Rich official docs, AI extracts context | Oral-tradition-centric know-how |
- Decide together with language (language-only first is failure prone).
- Pick mainstream + LTS (favorable on hiring, info, AI accuracy).
- Prefer convention-based (consistency over freedom).
- Avoid emerging FWs (long-term maintainability over buzz).
Equifax and the unpatched Struts (industry case)
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
Recording the decision rationale
Frameworks are tied directly to product lifespan, so recording the selection rationale as an ADR (Architecture Decision Record) is important. Here is a concrete example:
| Item | Content |
|---|---|
| Title | Adopt Next.js as the web framework |
| Status | Accepted |
| Context | Selecting a frontend FW for a B2C e-commerce site. SSR/SSG is a mandatory requirement for SEO |
| Decision | Adopt Next.js 15 (App Router) |
| Rationale | - SSR/SSG/ISR can be switched per requirement, balancing SEO and performance - Most adoption track record in the React ecosystem, with highest AI code-generation accuracy - Deployable not only on Vercel but also self-hosted or on AWS Amplify |
| Rejected alternatives | Nuxt.js: few Vue-experienced team members, high adoption/training cost. Remix: weak SSG support, limitations on build-time generation for product-list pages |
| Outcome | Product list via ISR (60s), product detail via SSG + on-demand regeneration, my-page via CSR |
When version upgrades or tech-debt discussions arise, having zero material on “why we chose Next.js back then” means zero basis for judgment. Having “why we chose this” visible at a glance later is the greatest value of an ADR.
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.
📚 Series: Architecture Crash Course for the Generative-AI Era (22/89)