My Tech Stack and the Philosophy Behind It
Sep 23, 2025 See all posts
People obsess over their tech stack. They plaster logos on their resumes and argue about frameworks on Twitter. It’s the wrong conversation. A stack isn’t a collection of hype; it’s a physical manifestation of an engineering philosophy.
Mine is built on a simple premise: clarity, efficiency, and long-term adaptability. I don’t choose tools because they’re popular. I choose them because they are well-designed, respect the underlying system, and get out of my way. This is not a final list; it’s a snapshot of a living system. The principles are permanent; the components are not.
The Guiding Principles
Before the tools, the rules.
- Simplicity is Non-Negotiable. Simple doesn’t mean easy. It means it has few moving parts. It’s predictable. I will always choose a tool with a transparent architecture over one that offers “magic.”
- Efficiency is the Goal. This applies to everything: runtime performance, resource consumption, and my own time. Fast feedback loops and low-latency tools are mandatory.
- Precision Over Familiarity. I don’t use a hammer for a screw just because I’m good with a hammer. If a tool is fundamentally a better fit for the problem, I’ll learn it. Sticking with a familiar but suboptimal tool is the definition of tech debt.
- Long-Term > Short-Term. Will this choice be a liability in five years? Does it lock me into a vendor? Does it have a massive, fragile dependency tree? I optimize for a future where I can still understand and maintain the system.
The Languages
Languages are cognitive tools. I choose them for how they shape thinking.
- Go (Backend): Fast, statically typed, and compiles to a single binary. Its concurrency model is simple and built-in. The standard library is robust. Go forces you to handle errors explicitly. It’s boring in the best way possible—it builds reliable, self-contained systems with zero fuss.
- Python (Glue & Data): Let’s be honest: Python is slow and its packaging is a mess. But its data and ML ecosystem (
pandas
, scikit-learn
, PyTorch
) is unmatched. I use it strictly for what it’s good at: analytics, automation scripts, and machine learning. With tools like uv
, the packaging pain is finally becoming manageable.
- TypeScript (Web): JavaScript with guardrails. Building anything non-trivial on the web without a type system is professional malpractice. TypeScript adds the necessary structure to build scalable and maintainable frontends.
- SolidJS (Frontend): I don’t use React. The Virtual DOM is a clever solution to a problem we can now solve better at compile time. SolidJS uses fine-grained reactivity, compiling down to direct DOM manipulations. It’s faster, simpler, and closer to the platform. The trade-off? A smaller ecosystem. I’ll take performance and a better core architecture over a sea of mediocre component libraries any day.
- Astro (Content Sites): Most of the web is not an application. It’s content. Treating every project like a complex single-page app is engineering malpractice. Astro gets this. Its islands architecture ships zero JavaScript by default. It sends HTML and CSS; interactivity is an opt-in enhancement for specific components, not a baseline requirement. Why ship a heavy framework to render a blog post? For anything content-first—docs, marketing sites, portfolios—Astro is the default. It’s fast, simple, and respects the platform. It treats JavaScript as a scalpel, not a sledgehammer.
- C (The Foundation): I don’t build products with C. I learn with C. To understand the machine, memory, and pointers, you have to speak its language. It’s a tool for sharpening my understanding of everything else I use.
The environment dictates the architecture. I choose platforms that grant control and efficiency.
- Desktop: EndeavourOS. An Arch-based distro that provides a minimal starting point. It gives me a rolling-release model with up-to-date packages without the bloat of mainstream operating systems. It’s a system I build and understand, not one that’s handed to me.
- Laptop: MacBook Air (Apple Silicon). I’m no fan of Apple’s walled garden. But the hardware is undeniable. The efficiency, battery life, and build quality of Apple Silicon are currently unmatched. It’s a pragmatic concession to physics. The machine “just works,” and that frees up cognitive overhead.
- Server: Ubuntu Server (LTS). Servers need to be stable, predictable, and secure. Ubuntu LTS provides a battle-tested foundation with long-term support. Bleeding-edge has no place in production; boring is a feature here.
- Containers: Alpine Linux. My container base images are Alpine. It’s ridiculously lightweight and has a small attack surface. Building on Alpine results in smaller, faster, and more secure images. Why ship a 1GB container when a 50MB one will do the job?
Data & Analytics
Data is useless without good tooling.
- PostgreSQL: The grown-up in the database room. Reliable, extensible, and standards-compliant. For my primary transactional database, I want zero surprises. Postgres delivers.
- DuckDB: The
sqlite
for analytics. An in-process, columnar database designed for speed. The ability to run complex analytical queries on Parquet files without spinning up a cluster is a superpower.
- PostHog: Product analytics I can own. I self-host it. It gives me event tracking and session recording without sending my data to a third party. It aligns with the principle of control.
- Jupyter: It’s clunky, but it’s the de-facto workbench for data exploration. Nothing else provides the same level of iterative, stateful analysis.
Infrastructure
I want to build on a foundation I understand and control.
- Linux + Podman: I don’t use Docker because I don’t like daemons I didn’t invite. Podman is daemonless, more secure (rootless by default), and integrates directly with
systemd
. It treats containers like regular processes, which is what they are. It’s a cleaner, more Unix-native approach.
- Caddy: A reverse proxy that just works. It handles automatic HTTPS via Let’s Encrypt with a ridiculously simple config file. A perfect example of a tool that solves a complex problem with a simple, robust design.
- Hostinger VPS: Control. Simplicity. Predictable cost. A simple Linux box with SSH access is a more transparent and cost-effective foundation than the baroque complexity of AWS.
Dev Workflow
My development environment is built for speed and focus.
- helix: My default editor. Modal, written in Rust, and zero-config. It’s incredibly fast and has sane defaults. For focused, individual work—writing scripts, config files, or small services—it’s unbeatable. It gets out of my way.
- VSCode + Zed (For Large Projects): I’m a pragmatist, not a purist. For massive, multi-faceted codebases or when collaborating with a team, the integrated environment of an IDE is more efficient. Zed is the ideal—fast, collaborative, and built with performance in mind. VSCode is the 800-pound gorilla; its extension ecosystem is sometimes a necessary evil. I use them when the project’s complexity justifies the overhead.
- uv: A replacement for
pip
and venv
written in Rust. It’s orders of magnitude faster. A long-overdue fix for a major bottleneck in the Python ecosystem.
- Git + GitHub: Git is a brilliant design. GitHub is the de-facto platform. No surprises here.
- systemd: It’s already on my server, it’s battle-tested, and it can manage services with simple unit files. Use the tools the system provides.
- Make/Taskfile: A simple, declarative way to define project commands like
build
and deploy
. Superior to embedding a mess of shell commands in a package.json
.
Native Mobile: A Pragmatic Escape Hatch
My default is Progressive Web Apps (PWAs). Build once with web tech, run everywhere. It’s the most efficient path for most applications.
But when a use case demands deep OS integration, background tasks, or performance that pushes the hardware to its limits, I won’t hesitate to go native. For that, it’s Swift/Kotlin. They are modern, well-designed languages backed by their respective platforms. It’s another application of “precision over familiarity”—don’t force a PWA to do a job a native app can do ten times better.
Why This Matters
My stack is a system designed to eliminate noise. It’s built on a foundation of small, sharp tools that do one thing well. It prioritizes performance, transparency, and long-term maintainability over hype cycles and resume-driven development.
The tools serve the system, not the other way around. Choose tools that disappear, that let you focus on the actual problem. The rest is just a distraction.
Enjoyed the article? I write about 1-2 a month. Subscribe via email or RSS feed.