Languages & selection
A language is not a popularity contest—it is a tradeoff among problem domain, team skill, and runtime constraints. This page captures selection dimensions, a compact map of families, and questions to ask in design review.
Selection dimensions
| Dimension | Questions | Signals |
|---|---|---|
| Problem domain | Latency, throughput, safety, delivery shape | Embedded / server / client / scripting |
| Type system | How many errors caught before run | Static strong vs dynamic + tests |
| Runtime | GC, ownership, VM, interpreter | Pauses, determinism, cold start |
| Ecosystem | Libraries, tooling, hiring, docs | Package mgr, LSP, official guides |
| Interop | Existing code, FFI, platform APIs | C ABI, JNI, Wasm, ObjC/Swift |
| Maintainability | Team skill, migration cost | Module boundaries, refactor tools |
tip
Default: Prefer a language the team already masters with a mature ecosystem; add a second language only when metrics prove a bottleneck (latency, memory, binary size).
Type systems at a glance
| Style | Examples | Upside | Cost |
|---|---|---|---|
| Static strong | Rust, Swift, Go, Java, TS (strict) | Clear contracts, safer refactors | Boilerplate, generics curve |
| Gradual | TypeScript, Python + hints | Easier migration | Needs lint for consistency |
| Dynamic | Ruby, untyped Python | Fast prototypes | Regressions need discipline |
Practice: Enable strict mode in TypeScript/Python; centralize boundary types (API DTOs, config); stop any from spreading.
Language map (personal notes)
| Language | I reach for it when | Think twice when |
|---|---|---|
| Swift | Apple UI, system APIs, safer concurrency defaults | Linux-only server with no Swift bench |
| TypeScript | Web full stack, tooling, JSON/API-heavy work | CPU-bound core without native/Wasm path |
| Python | Data scripts, glue, internal tools | High-concurrency long-lived sockets without asyncio + load tests |
| Go | Simple concurrent services, CLI, sidecars | Rich domain models without team discipline |
| Rust | Perf/safety-critical pieces, FFI, infra | First version of CRUD product (iteration cost) |
Not a ranking—validate with measurements per project.
Review checklist (PR / design)
- Does a new dependency introduce a second memory or async model?
- Are public APIs typed with explicit error shapes?
- Reusing existing format, lint, and test harness?
- Are scripting languages confined to boundaries (build, migrate, ops)?
Performance vs language
Language is rarely the first bottleneck. Before switching:
- Profile: CPU flame graphs, allocations, lock wait.
- Algorithm & I/O: N+1 queries, serialization, blocking calls.
- Boundary: Native/Rust/C on hot paths; keep business code in the incumbent language.