$ ls choices/
Every tool on the works page is a decision, not a default. This is why: when I reach for each one, when I don't, and the calls I've made with it in production. Anyone can list a stack. The reasoning is the work.
elixir lang
Reach for it when concurrency and fault-tolerance are the product, not a feature bolted on later.
go lang
The heavy-IO scalpel. When your language is the wrong tool for the workload, switch the workload, not the hardware.
ruby on rails framework
Velocity early. Rails' conventions are the fastest path from idea to shipped, until the workload outgrows it. The job is knowing when that is.
crystal lang
Type-safety with Ruby's soul. Compiled speed and static types that still read like Ruby. My answer when I want both, and the language behind several of my OSS projects.
rust lang
Safety and speed without a GC, a compiler that catches what tests miss. What I reach for more and more lately; han and darkrun are built on it. Not the move when you just need something shipped yesterday.
typescript lang
Types are the cheapest guardrail in the JS world. Anywhere code lives in the JS/Node/web ecosystem and has to last, TypeScript turns a class of runtime bugs into compile errors. The default, not the upgrade.
react client
The safe default for the web. Ecosystem, hiring pool, mental model all there. But I'll almost always lead with React Native instead: same engine, three platforms from one codebase. Plain React is for when the surface is truly web-only.
react-native client
One codebase: iOS, Android, and web (via Expo + react-native-web), with Windows/macOS community-supported. Bridge gone, OTA updates, the price keeps dropping. Shared velocity over native polish, until native polish is the product.
kubernetes infra
Earn it. The cheapest path to stability at real load, and an expensive mistake before you're there.
terraform infra
The tracks. If infrastructure isn't code, your speed has a ceiling you'll hit at the worst possible time.
gcp cloud
Cost, control, performance. Migrated to it more than once for the same three reasons, and they held.
robust-ci delivery
The goal is a CI you trust. The tool is downstream. GitLab, GitHub Actions, whatever delivers a pipeline that catches what's broken before users do. Robustness is the requirement; the brand is fashion.
argo-cd gitops
GitOps, done right. Git is the source of truth; the cluster reconciles to match. Auditable, reversible, boring, and the right tool for app deploys that Terraform should never be doing.
postgres data
Just use Postgres. The relational core that also moonlights as your queue, cache, search, and document store: one engine instead of five. Reach for something else only when you've genuinely outgrown it.
graphql api
When the client owns the shape. Worth the complexity when many surfaces hit one graph; overkill when they don't.
distributed-systems method
Scale is a design problem before it's a code problem. Decide where state lives before you write a line.
monorepo method
One repo, one source of truth, my default for an org. Atomic cross-cutting changes, shared tooling, and increasingly the one context boundary an LLM can actually reason over. The whole system in one place, for humans and agents both.
typed-languages method
Let the compiler be the tireless reviewer. Static types catch a whole class of bugs before they ship, the cheapest guardrail there is. The instinct behind Crystal, Rust, and TypeScript: pay a little up front, stop paying at 2am.
autonomy-with-guardrails method
Move without asking, inside rails that make it safe. Autonomy is the speed. Guardrails (tests, CI, review, types) are the tracks that keep speed from becoming a derailment. Neither half works alone.
gitops method
Git is the source of truth; the system reconciles to match. Deploys are merges, rollbacks are reverts, the audit log writes itself. The rule that makes it sing: TF for the building, Git for the lights.
api-first method
Build the open API first, dogfood it, then invite others in. Integration leads to expansion. Every team that builds on your API makes the product bigger than you could grow it alone. The API is the product surface.
write-it-down method
Get the map out of people's heads. Decision records, runbooks, written intent: the infrastructure that survives losing someone, and the context a fleet needs to be useful. Step one of the agent era.
feature-flags method
Decouple deploy from release. Ship dark, roll out by cohort, kill a bad change with a toggle instead of a rollback. The runtime half of progressive delivery. Flag debt is real, so clean up after.
observability method
You can't verify what you can't see. The signal that gates a release and answers 'is this actually working?', not 'are the tests green.' When generation is free, knowing what's true is the job.
claude-code agentic
The volume layer. Point it at the right problem with someone who can tell when it's lying, and it's a force multiplier. Drop it in cold and it's confident garbage at scale.
the-agent-fleet workflow
Generation is free; verification is the job. A fleet of agents holds the volume (opening MRs, drafting, scoring) and a human holds the map. Multiply judgment by a fleet, not zero by a fleet.
llm-apis build-on
Build on the model, not around the hype. Worth it when the task is genuinely fuzzy; a liability when a plain function would do.
local-llms models
Own the model, keep the data. Open-weight models like Qwen and the latest DeepSeek are closing on the frontier fast. When privacy, cost-at-scale, or control matter, local beats a rented API for a growing slice of the work.