Stack
What I would pick if I could choose freely, what I live with day to day, and what I have left behind.
Dream stack
Technologies I love and would choose for any new project.
OS / distro
Linux is simply the better development platform: packages, CLI tooling, and stability are all there by default.
- NixOS: reproducibility, declarative configuration versioned in a private git repo (+ testability like unit tests), almost all packages I use available,
nix developto have a dev setup, security. All this make me drop debian/ubuntu based Linux. Nix configuration can be hard to write, and some changes require a reboot to apply.
Languages
- Rust: memory safety without a garbage collector, predictable performance, and a type system that makes invalid states hard to represent — algebraic enums, exhaustive pattern matching, no null. Cargo is the best build tool I have used: one command to build, test, add dependencies, or publish, with a consistent experience across every project. The two genuine pain points are async complexity (the model works but lifetimes and pinning add friction) and the borrow checker: I know what I want, but occasionally spend more time convincing the compiler than writing the logic. Both are acceptable trade-offs for what the language gives back.
Libraries & frameworks
- FastAPI for Python: async-first, and type hints do real work — route parameters, request bodies, and response models are all validated automatically via Pydantic, and OpenAPI/Swagger documentation is generated for free from the same annotations. Dependency injection is built in and keeps handlers readable and testable. It gives structure where Flask leaves decisions to you, without the weight of Django.
Tools & infra
When choosing a CLI tool I favour the implementation language: Rust first, then Go, then C or C++, then Bash, then Python. A Rust binary gives memory safety, a single static binary with no runtime dependency, and predictable performance. Where a Rust alternative exists and is mature, I replace the original. Examples: jq → jaq, GNU coreutils → uutils, sudo → sudo-rs.
Daily driver
Technologies I use regularly — at work or in practice — that I consider good enough.
OS / distro
Languages
- Python: the right choice for professional work — the ecosystem is wide enough that there is almost always a library for the problem at hand — and many performance-critical ones are thin bindings over native C or Rust libraries, so you get near-native speed without leaving Python — and the language is readable enough that colleagues can pick it up quickly. Fast to iterate on, good for scripting, networking, data, and security tooling. Modern tooling has improved the experience considerably:
uvfor dependency management,rufffor linting and formatting,pytestfor tests,pydanticfor data validation. Two lasting frustrations: type hints are optional and unenforced at runtime, so discipline is still required to get their full benefit; and the packaging story, while better withuv, spent years being unnecessarily fragmented.
Libraries & frameworks
- Flask for Python: minimalistic and stays out of the way — decorators for routes, nothing imposed on project structure. That freedom is also its cost: every architecture decision is yours to make, which adds up as complexity grows. It works well for smaller services and scripts that need an HTTP interface, but for anything larger I would now reach for FastAPI instead.
Tools & infra
Retired
Technologies I have consciously moved away from and would not pick again.
OS / distro
- Windows: Windows 10 was acceptable. Windows 11 is slower, heavier on RAM and disk, and progressively less configurable than earlier versions (XP/7 gave much more control). Updates can silently override user settings such as the default browser or PDF viewer, which is not acceptable on a machine I control. Shipping advertising inside a paid OS is also a hard line for me.
Languages
I cannot learn every language well, so I deliberately narrowed down: Python for professional work, Rust for personal projects. Most of what is listed below was retired not because it is inherently bad, but because one of those two already covers the same ground better for my use cases.
- ColdFusion: used at work years ago. Too niche, largely dead, no reason to return.
- PHP: I used versions 3, 4 and briefly 5, before modern frameworks existed. PHP has improved substantially since then, but by the time it did, Python with Django or Flask or FastAPI already covered the same web use cases for me.
- Java: RAM-hungry and not practical on ARM devices — NAS, routers, low-power VMs, the environments I care about. The ecosystem (tooling, documentation, libraries, IDEs) is genuinely strong, which is worth acknowledging.
- JavaScript: I learned it during the browser-war era when IE, Firefox and Chrome all behaved differently. I drifted away from frontend work and never came back. Node.js and server-side JS did not attract me once Python was already filling that role.
- C / C++: The language itself is not the problem. The build tooling is — CMake, Autotools and Meson all coexist with no clear standard, and APT package versions often lag behind what a project requires, forcing manual source builds. The community tends to assume a high baseline and is not welcoming to newcomers navigating that complexity. Rust covers the same problem space (systems programming, performance, no garbage collector) with Cargo, a coherent build system, and memory safety by default. There is no reason to go back.
- C#: Used briefly for a work side project involving Silverlight. Never went deeper. .NET has since become cross-platform and more interesting, but it is not a gap I have needed to fill.
- Delphi / Pascal: Niche, sparsely documented outside its own ecosystem, and with limited community and career trajectory. Would not choose it today.
Libraries & frameworks
- Django and Django Rest Framework (DRF) for Python: this web framework is batteries included, but that becomes a weak point as complexity grows. Using the ORM, if you use inheritance and query for parent classes, you cannot get children back as their concrete type (SQLAlchemy handles this with polymorphic loading). Full async support was a long time coming — async views arrived in 3.1, but the ORM did not follow until 4.1. Lastly, it is not designed for Domain-Driven Design: the Active Record pattern and tight coupling between models and persistence work against DDD’s separation of domain logic. I feel more like I’m doing Django than Python.
Tools & infra
- Node.js / npm tooling: I avoid tools built on the npm ecosystem. Supply chain attacks happen across all ecosystems, but npm is specifically risky because of extreme dependency depth — a trivial package routinely pulls in hundreds of transitive dependencies, each an unaudited attack surface. The concrete illustration: building a JS project once left me with about 40,000 files on disk. That is not a dependency graph I can reason about or trust. I prefer tools where the dependency tree is shallow enough to be auditable.