About this article
This article is the first deep dive in the “Software Architecture” category of the Architecture Crash Course for the Generative-AI Era series, covering how to choose a programming language.
“The language ties down the framework, and the framework ties down who you can hire.” Once chosen, it binds the project for a decade — a hard-to-undo decision. The article covers the major nine languages (TypeScript, Python, Java, C#, Go, Rust, Ruby, PHP, C/C++) and selection criteria across the four axes of scale, use case, talent market, and AI-generation accuracy.
What is programming-language selection in the first place
Programming-language selection is, in a nutshell, “deciding which language to write your system in.”
Imagine learning a foreign language. English (TypeScript / Python) has the most speakers and resources; German (Java) has strict grammar and suits large enterprises; Latin (C / C++) is classical and fast but extremely hard to learn. Once you start writing in a language, all of the team’s talent, libraries, and know-how accumulate around it, and switching to another language later costs as much as “retranslating every paper you’ve ever written.”
Why language selection matters
What happens if language selection is taken lightly? If no one on the market can write that language in 5 years, you can’t hire or hand off — the system becomes technically stranded. Today is the era of picking the right language per use; mixing different languages for frontend and backend is normal.
Language selection is a One-way Door on par with overall structure. Decide it with a 5- and 10-year talent-market view.
”How many people will be writing this in 5 years?”
Old-school enterprise backend was Java-dominant; today is the era of picking the right language per use. Web systems standardly mix different languages on frontend (browser) and backend (server).
Computers natively understand only machine code. Programming languages are how humans drive them — source code gets translated to machine code by a compiler for execution.
Language selection, like overall structure, is a One-way Door. Decide it with a 5- and 10-year talent-market view.
Execution-style classification
Languages split by execution style into three groups. The style sets the trade-off between processing speed and development speed — the underlying property behind language selection.
flowchart LR
SRC([Source code])
COMP["Compiled<br/>C / C++ / Rust / Go"]
INTR["Interpreted<br/>Python / Ruby / PHP"]
JIT["JIT<br/>Java / C# / JavaScript"]
SRC --> COMP --> MC1[Machine code<br/>fast in production]
SRC --> INTR --> MC2[Sequential exec<br/>fast development]
SRC --> JIT --> IL[Intermediate language] --> MC3[Compiled at runtime<br/>middle ground]
classDef src fill:#fef3c7,stroke:#d97706;
classDef comp fill:#dbeafe,stroke:#2563eb;
classDef intr fill:#fae8ff,stroke:#a21caf;
classDef jit fill:#f0f9ff,stroke:#0369a1;
classDef out fill:#dcfce7,stroke:#16a34a;
class SRC src;
class COMP comp;
class INTR intr;
class JIT,IL jit;
class MC1,MC2,MC3 out;
| Execution style | Languages | Mechanism |
|---|---|---|
| Compiled | C, C++, Rust, Go | Translated to machine code ahead of time. Fast, but recompile on every change |
| Interpreted | Python, Ruby, PHP | Read and execute line by line. Immediate feedback, but slow |
| JIT | Java, C#, JavaScript | Build intermediate language; compile at runtime. OS-independent and reasonably fast |
Compiled is “production performance,” interpreted is “development cycle speed.” JIT (Just-In-Time compiler — turns into machine code on the fly at runtime) is the middle-ground compromise.
C / C++
C (1972) is one of the earliest programming languages; the simple structure produces extremely fast execution. Lacking automatic memory management and OO, developers handle those manually.
C++ (1983) extends C with memory management and OO under the “zero-overhead principle,” maintaining C-comparable speed. Since 2011, modern features ship every 3 years; still active.
| Strengths | Weaknesses |
|---|---|
| Overwhelming execution speed and stability | No automatic memory management (C) |
| Strong on hardware control | Extremely high learning difficulty |
| Massive library legacy (C++) | Verbose, low readability |
Main uses: embedded, OS / system software, AI library cores (PyTorch, TensorFlow), high-end games (Unreal Engine).
C’s domains are being replaced by Rust at speed. C/C++ won’t disappear due to the legacy footprint, but priority for new projects is dropping.
C# / .NET
C# (2000, Microsoft) is a cross-platform language with garbage collection and OO. Runs on Windows, Linux, Mac, iOS, Android, etc., though without C/C++ compatibility.
Microsoft maintains it actively with modern features. Excellent affinity with Microsoft products and Azure; broadly used from web apps to enterprise systems. Standard language for the Unity game engine — adopted in many mobile and console titles.
| Strengths | Main uses |
|---|---|
| Excellent fit with Microsoft / Azure | Apps using Microsoft services |
| Good balance of performance and productivity | General web apps (ASP.NET Core) |
| No conspicuous weaknesses | Game development (Unity standard) |
C# is the default candidate where Microsoft services are central.
Java
Java (1996, Sun Microsystems; Oracle since 2010) provides OO, multi-threading, garbage collection, and runs on the JVM (Java Virtual Machine), making it OS-independent with high speed and stability.
Long-dominant in enterprise systems, still active. Updated semi-annually with cloud-optimization features. Spring family is mature, the standard for business app development.
License trap
Java has two licenses. OpenJDK is free open source like other languages; Oracle JDK commercial use requires per-employee licensing.
The fees are extremely high, calculated including non-developers. A 1,000-employee company pays around $200k/year; 30,000 employees pays around $2.4M/year. Oracle JDK support includes legal protection, support for older versions, and 24/7 phone support — often required by compliance at public-sector and financial firms.
| License | Cost | Main rationale |
|---|---|---|
| OpenJDK | Free (open source) | General use |
| Oracle JDK | Annual license fee (high) | Public sector / financial support requirements |
Companies are migrating to free OpenJDK-compatible Amazon Corretto. Reasons to deliberately pick Oracle JDK are shrinking.
Oracle JDK costs license fees in commercial use. Amazon Corretto / Eclipse Temurin are the alternative defaults.
Python
Python (1991) provides functionality similar to other major languages, with “readability-first design” as the defining trait. Less code than Java or C#, with mandatory indentation-based blocks producing readable code regardless of who writes it.
Strong community, with the richest libraries especially in AI and data science — AI development effectively standardizes on Python. Interpreted, so raw speed is slow; but most libraries it calls are written in C/C++, so actual execution isn’t that slow.
| Strengths | Weaknesses |
|---|---|
| Overwhelming readability | Raw speed is somewhat slow |
| Effective standard in AI / data analysis | Dynamic typing weakens large-scale projects |
| Low learning cost | GIL (Global Interpreter Lock — restricts to one thread at a time) |
| Extremely rich libraries | — |
Main uses: AI / ML / data analysis, general web apps (Django, FastAPI).
In AI / data science, no other language is in serious contention.
Ruby / PHP — current status of scripting languages
Ruby (1995, Yukihiro Matsumoto) is famous for “Ruby on Rails.” Rails generates feature scaffolding with one command and lets you build web app prototypes fastest by following conventions. Rails itself is heavy, so it’s a poor fit for FaaS (Function as a Service) and microservices; selection opportunities outside web are decreasing.
PHP (1995) was born for web, embedded in HTML to generate dynamic pages — explosively popular. WordPress, powering ~75% of websites globally, is in PHP — still the largest backend language by deployment count. PHP 8+ added JIT and improved typing; Laravel and Symfony are mature.
| Language | Position |
|---|---|
| Ruby on Rails | Strong choice for individuals / small teams launching web apps fastest |
| PHP + Laravel | WordPress projects, small/mid web sites, existing PHP maintenance |
Active new-project selection has decreased, but the legacy is huge so they remain major languages for now.
JavaScript
JavaScript (1995, Brendan Eich at Netscape, ~10 days) is the browser-side language. Spec is standardized as ECMAScript; complex parts from history persist, but yearly updates evolve it.
The biggest pivot: 2009’s Node.js. JavaScript became a general-purpose language outside the browser, opening “full-stack” with one language for frontend and backend. Event-driven and async I/O make it strong on high-concurrency web servers and AWS Lambda-style serverless.
| Strengths | Weaknesses |
|---|---|
| De facto standard for frontend | Dynamic typing weak at large scale |
| Full-stack with Node.js | Spec complexity from history |
| Largest npm ecosystem | Async syntax is distinctive |
| Abundant learning resources | Lacks type safety |
For backend, almost all projects have moved to TypeScript. Picking raw JS for backend outside small scripts is an obsolete choice.
TypeScript
TypeScript (2012, Microsoft) adds static typing and OO to JavaScript. Backwards-compatible with JS — existing JS code runs as-is. Compile-time type checks dramatically reduce runtime bugs.
For frontend, all major frameworks (Next.js, React, Vue, Angular) support TS — “TypeScript dominance” is the state. Backend runs on Node.js, Deno, Bun runtimes; especially BFF (Backend For Frontend, a frontend-specific intermediate API layer) and microservice adoption is surging. Sharing language and types between frontend and backend has a large team-productivity effect.
| Runtime | Trait |
|---|---|
| Node.js | Most adopted, rich track record and info |
| Deno | Successor by Node.js’s author. Strong on security and TS-native |
| Bun | 2022 high-speed runtime. Node.js compatible, several times faster startup |
For new web projects, frontend and backend on TypeScript is the current default.
Rust
Rust (announced 2010 by Mozilla; 1.0 in 2015) is a compiled language guaranteeing memory safety. Without garbage collection, “ownership” prevents memory leaks and data races at compile time.
Steep learning curve, but once mastered you get C/C++-class execution speed and modern-language ergonomics. “Replacement candidate for C/C++” adoption is accelerating, ranking high in Stack Overflow’s “most loved language” survey.
| Adoption area | Examples |
|---|---|
| Systems | Linux kernel (parts), Windows component adoption beginning |
| Browsers | Firefox rendering engine (Servo) |
| Web / infrastructure | Cloudflare Workers, Dropbox storage backend |
| WebAssembly | Effective first choice for Wasm targets |
| CLI / tools | Replacements for ripgrep, fd, esbuild |
For new projects where performance and safety are absolute requirements, Rust is the most momentum-rich language now.
Go
Go (2009, Google) thoroughly pursued simplicity. Just 25 keywords; reachable to business-writing level in a week. Reportedly born from frustration with C++ builds taking 35+ minutes inside Google.
The biggest strength is overwhelming presence in cloud-native. Docker, Kubernetes, Terraform, Prometheus — most modern-infrastructure tools are written in Go. Statically compiled to a single binary and starts fast — strong fit for containers and FaaS, default for microservice API servers.
| Strengths | Weaknesses |
|---|---|
| Low learning cost | Prioritizes simplicity over expressiveness |
| Lightweight concurrency via goroutines | Late generics support (came in 1.18) |
| Single-binary distribution | Fewer OO features |
| Fast startup, fits FaaS / containers | — |
Adoption: Docker / Kubernetes / Terraform / Prometheus / etcd / Google, Uber, Netflix microservices.
For new cloud-native infrastructure, Go is the first candidate.
Major selection criteria
Language selection isn’t decided by trend or preference; multiple axes need joint evaluation matched to project requirements. Once chosen, the language binds the project for years, so decide carefully.
- Where the application runs (runtime / OS / cloud)
- Functional and non-functional requirements (performance, concurrency, consistency)
- Implementation effort (framework richness, dev speed)
- Available engineers (in-house skill, external talent market)
With AI-driven (vibe-coding) development spreading, AI compatibility has joined the criteria. Type-rich languages (TypeScript, Rust, Java) let AI infer intent accurately; languages with abundant training data (Python, JavaScript) generate higher-quality code.
Selection by case
New web app (API-centric, frontend-integrated)
TypeScript (Node.js / Bun). Share types between frontend and backend, balance dev speed with type safety. The most balanced current choice.
New web app (large-scale, enterprise, robustness focus)
Java / C#. Long operational track record, deep talent market, and mature frameworks (Spring Boot / ASP.NET Core). Still primary candidates in public sector and finance.
High-speed, low-resource servers
Rust / Go. For microservices and container-first, Go wins on startup speed and binary size. Rust comes in if extreme performance and memory safety are required.
AI / ML / data analysis
Python only. The library ecosystem is orders of magnitude ahead — practically no other choice. PyTorch, TensorFlow, pandas all assume Python.
Solo / small-team fastest prototype
Ruby on Rails / PHP + Laravel. The scaffold command auto-generates the skeleton; one person can launch a web app in a short period.
Embedded / OS / hardware control
C / C++ / Rust. New: Rust is a candidate; existing maintenance still requires C/C++.
Maintaining / extending existing systems
Continue with the existing language. Rewriting in a different language almost never pays.
Language × talent-market practical ladder
Knowing “how many will be writing this in 5 years” in numbers makes selection sharper. Approximate Japanese hiring-market sense as of April 2026:
| Language | Domestic engineer pop | Hiring difficulty | 5-year continuation | Main domain | Suited case |
|---|---|---|---|---|---|
| JavaScript / TypeScript | 500k+ | Low (easiest to hire) | Expanding | Web, mobile, BFF | Web apps wanting type-sharing between front and back |
| Java | 400k+ | Low-mid | Continuing | Enterprise / finance / public | Enterprise systems prioritizing robustness and long-term maintenance |
| Python | 300k+ | Low-mid | Expanding (AI demand) | AI / data / web | Development centering on AI and data analysis |
| PHP | 200k+ | Low | Shrinking | WordPress / legacy | WordPress projects or existing PHP asset maintenance |
| C# / .NET | 150k+ | Mid | Continuing | Unity / Microsoft stack | Azure-centric or Unity game development |
| Go | 50k+ | Mid-high | Expanding | Cloud-native / microservices | Container and microservice infrastructure |
| Ruby | 50k+ | Mid-high | Flat | Rails legacy / startups | Fastest prototype development with a small team |
| Rust | 10k+ | High | Expanding (niche) | Systems / Wasm / infra | Absolute requirements for extreme performance and memory safety |
| Kotlin / Swift | ~50k each | Mid | Continuing | Mobile-only | iOS / Android native app development |
The empirical rule: “adopting a language with under 100k domestic engineers takes 6+ months to hire.” A startup posting “Rust required” sees applications drop 10x. For mid-career enterprise hiring, anything outside the TypeScript / Java / Python big three must be accepted as causing year-scale planning impacts.
Pick by numbers: “how many people will be writing this in 5 years.” Cases of niche-language teams stuck on hiring keep coming.
Language migration / selection traps
| Forbidden move | Why |
|---|---|
| ”Big Bang Rewrite” — replacing language while rewriting | Netscape 1998 lost 3 years on a rewrite and lost the browser wars. Phased migration (Strangler Fig) is the only realistic answer |
| Adopt an emerging language “because it’s trending” for an MVP | Engineers don’t come; switching to another language during growth phase |
| Use dynamically typed languages (Python / Ruby) past mid-scale | Type-absence cost surfaces 3 years later. Large-scale defaults to typed languages (TypeScript / Java / Go / Rust) |
| Use Oracle JDK commercially without checking the license | Per-employee × annual fee — at 1,000 employees, ~$200k/year. Amazon Corretto / Eclipse Temurin are the alternative defaults |
| 5+ languages mixed in one project | Maintainers scatter; nobody understands the whole. Two languages (e.g. frontend TS + backend Go) is enough |
| Run non-LTS language versions in production | Short window before security patches end; yearly migration |
| ”AI can write it, so a niche language is fine” | AI accuracy scales with training-data volume; niche languages have hallucinations in generated code |
| Unifying all projects on one language | Frontend/backend in one language works, but forcing AI processing into TS too is unreasonable; right tool per use is the realistic answer |
| Selecting a language by trend alone | Trends are temporary; without checking “will the talent market still exist in 5 years?”, you ride the decline |
Language selection is a One-way Door — you can’t go back once you start. With multiple candidates, always quantify on “hiring plan × 5-year talent market × AI-generation quality” before deciding.
“Fun to write” vanishes against hiring difficulty in 3 years.
AI decision axes
| AI-era favorable | AI-era unfavorable |
|---|---|
| TypeScript (types + info + full-stack) | Dynamic languages (Perl, Ruby) instability at scale |
| Rust, Go (type safety, standardization) | Custom DSLs, niche languages |
| Python (most training data) | Custom extensions, in-house languages |
| Standard-framework compliance | Niche implementations, custom patterns |
- Narrow effective candidates by use (AI / web / high-perf / systems).
- Talent-market depth (can you hire 10 years from now?).
- AI-generation accuracy (type strength × info volume) for the final call.
- Continue if existing assets exist (rewriting almost never pays).
”How many in Japan write that?” (industry case)
When a junior engineer suggests “I want to use this in production” for a niche language they like, the senior architect asks “how many people in Japan write that?” and the proposer falls silent. This scene repeats in many places. The feeling of fun in writing and the management decision of being able to hire successors are different layers.
There are stories of young engineers underestimating Go’s then-niche status, proposing it for production, and going silent when their senior asked “how many on this team can write it after you?” Lesson: “language selection is technical decision and recruiting strategy at once.”
Niche languages should be enjoyed in personal study and validation projects; for production, default to “a language 5 years from now that thousands of people in Japan will still write.” The price of sharp selections is paid by the successor team.
Fun is cost. Talent is asset.
What you must decide — what’s your project’s answer?
Articulate your project’s answer in 1-2 sentences for each:
- Main language (TypeScript / Python / Java / C# / Go / Rust, etc.)
- Runtime / version (default to latest LTS)
- Per-use additional languages (AI in Python, infra in Go, etc.)
- Typing policy (TypeScript
strict, Python type hints depth) - License check (Oracle JDK vs OpenJDK / Corretto, etc.)
- Frameworks paired with the language (Spring / FastAPI / Next.js, etc.)
- 5-10 year talent supply outlook
Recording the decision rationale
Language selection directly affects team composition, hiring, and maintenance cost, so documenting the rationale as an ADR (Architecture Decision Record) is essential. Here is a concrete example:
| Item | Content |
|---|---|
| Title | Adopt TypeScript as the primary backend language |
| Status | Accepted |
| Context | Selecting a backend language for a new SaaS product. Frontend is already confirmed as React (TypeScript) |
| Decision | Unify the backend on TypeScript (Node.js LTS) as well |
| Rationale | - Type definitions and validation logic can be shared with the frontend, boosting development efficiency - 5 of 6 team members have TypeScript experience, minimizing additional learning cost - The npm ecosystem is rich and AI code-generation accuracy is high |
| Rejected alternatives | Go: no type sharing, increasing schema-sync cost between front and back. Python: weak type safety, more runtime errors at scale |
| Outcome | Adopt a front/back monorepo with a shared package for centralized type definitions |
Even a decision that seems obvious at project start will inevitably spark “why TypeScript and not Go?” when team members rotate a year later. Having “why we chose this” visible at a glance later is the greatest value of an ADR.
Summary
This article covered how to choose a programming language — major-language traits, talent market, AI-era judgment.
Web -> TypeScript, AI / data -> Python, enterprise -> Java/C#, cloud-native -> Go, extreme performance -> Rust. The 2026 split. Niche languages stay in hobby; production leans on the mainstream. That saves both hiring and long-term maintenance.
The next article covers overall structure (monolith vs microservices vs modular monolith).
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 (18/89)