Ship, then polish
The best software starts ugly and gets refined. I've seen too many projects die in the planning phase — including my own, in the years before I learned this. Build the thing, put it in front of users, and iterate based on real feedback. The version you imagined in planning is almost never the version that actually helps anyone.
This is how Karmpath Architecture Decisions was built — three failed iterations before the product found its shape, each one teaching something the previous hadn't. The 17-month build that followed was fast because the first three iterations answered the questions that planning couldn't.
Infrastructure is a product
Treat your servers, pipelines, and configs with the same care you treat your user-facing features. Documentation, runbooks, monitoring, backups — these aren't operational overhead, they're features the next developer (or future you at 2am) will depend on.
The Prachyam Infrastructure Deep Dive project is the clearest example I have: replacing significant recurring SaaS costs with self-hosted equivalents required the same product thinking as building a user-facing feature. Design the failure modes, document the recovery path, build the monitoring before you need it.
The compiler is your best friend
Rust taught me this viscerally. When the borrow checker rejects your code, it's preventing a bug you would have shipped in any other language. The discipline of ownership and lifetimes makes you think about resource management differently — and that thinking transfers to every language you touch, including the ones that don't enforce it.
The zero-TypeScript-error rule I enforce on every project comes from the same instinct. A type error the compiler catches is a bug you don't debug in production.
Simplicity over cleverness
The best code is code that the next developer can understand in 30 seconds. Every abstraction should make the system easier to reason about, not harder. If you need a comment to explain what the code does, the code is too clever. If you need a paragraph to explain the architecture, the architecture has too many moving parts.
The recurring pattern I've noticed: clever code looks like a demonstration of skill and behaves like a maintenance liability. Simple code looks like anyone could have written it and behaves like it was written by someone who understood the problem completely. Those two things are the same.
Look at the default, ask if it's optimal
The throughline across most of my projects — X-Type layout, self-hosted mail, custom MCP tooling, the Hyprland rice, the keyboard-driven macOS environment — is the same question applied to different surfaces: is this default actually designed for my situation, and if not, what would be better?
The question is not "can I build something better than the default?" It's "is there evidence that something better is warranted?" When the answer is yes and the evidence is there, doing the work is straightforward. See Lessons from Infrastructure for how this plays out in practice.