How I use an anti-fragility mindset to learn and ship software
Why I needed a different way to learn software
Learning through doing wasn’t new to me. In fact, that was how I learn to code in bootcamp. The teaching philosophy there was to introduce the concepts just enough to get us started, push us straight into building exercises and projects to reinforce learning.
At the time, though, I didn’t fully internalize the approach. The bootcamp was highly structured, and I mostly followed the structure without reflecting on why it worked. Once the bootcamp ended, my learning habits slowly drifted back to something more passive: learning through absorption.
That meant reading textbooks, watching tutorials, planning my learning paths, preparing materials, and reading documentations for tools I had not even used yet but thought I might need someday. It felt productive, like I was constantly learning, but it produced almost no real output.
The pain showed up when I actually tried to build something. I realized I couldn’t apply much of what I had “learned” to solve real problems. Even building a simple app from scratch took a long time. Deployment was worse. I kept putting it off because I didn’t understand it. When that discomfort hit, I retreated back into tutorials and preparations to calm myself, almost like a drug. And the vicious cycle repeated.
What anti-fragile means in practice (for software)
Instead of trying to understand everything upfront or having a well structured plan before I start, I now embrace uncertainty more intentionally. I learn just enough to get me started, and let my actions guide the next steps. I also try to ship as early as possible because it exposes gaps in my understanding better than spending hours reading documentations or watching tutorials. Not having a well structured plan before starting can often lead to many small failures that slow progress down, but I have learned to accept that as the entry price for progress. Slow progress is still progress, and it beats not moving at all.
Technical Examples
SQLite vs PosgreSQL
I chose SQLite even though I was not confident it was “production-ready” or future-proof. I didn’t fully understand either SQLite or PosgreSQL. All I knew was that PosgreSQL was considered more powerful and more scalable. That made me worry that I’d hit the limitations quickly and end up paying a high cost to switch later.
In practice, none of those concerns showed up. I have not run into any database issues that signal a need to switch, which taught me that worrying about scalability too early often creates problems that aren’t real yet.
DigitalOcean vs AWS
I knew AWS was the industry standard, but the flexibility it offered also comes with significant cognitive overhead. Learning and configuring all of the options would have delayed my main goal: deploying the app. DigitialOcean, by contrast, was simpler. It was also familiar since I had deployed an app on it before, and its setup felt more straightforward.
I hesitated because I feared I’d be missing a great opportunity to learn AWS properly especially since it is a skill that many companies value. In the end, that fear didn’t matter at this stage. I was deploying a simple blog, and the time and mental energy required to maneuver through AWS would have outweighed the benefits. The trade-off simply wasn’t worth it.
Shipping before understanding
Publishing this blog follows the same pattern, I was not ready. In fact, I hadn’t even decided whether this should be a blog or a portfolio site. All I knew was that I wanted to create a site to share my work to the world. Even after settling on a blog, I didn’t know what I wanted to write or how to approach it.
Shipping early exposed problems that I couldn’t have predicted. For example, I ran into the Tailwind asset compilation issue that only occurred on Apple silicon when using Docker’s virtualization framework. That problem would never have surfaced if I had stayed in planning mode.
If I had waited until I felt ready, this post wouldn’t even exist. I would still be reading about deployment, comparing VPS providers, and doing cost-benefit analyses on databases. Shipping early, even when it’s ugly, gets the ball rolling and creates real problems that guide the next actions. Understanding is built inside that loop, not before it.
The decision rules I follow now
- I ship as soon as the bare minimal viable product works, even if it’s still ugly.
- I don’t worry about problems that aren’t real yet.
- I stop researching once I know enough to get started.
- I treat uncertainty as the signal to act, not to prepare more.
- Preparations aren’t actions.
- I treat actions as the precursor to understanding
- I use LLMs as assistants that suggest directions, not replacement of my own thinking.
Who this approach works for?(and who it doesn’t)
This approach works well for:
- People who feel the need to understand everything and and often fall into the rabbit holes.
- Perfectionists who delay shipping until things feel “ready”.
- Forecasters who spend a lot of time worrying about hypothetical future problems.
- People prone to decision paralysis
- People who rely heavily on LLMs to do the thinking for them.
This approach does NOT work well for:
- People who don’t reflect on their failures or learn from them.
- People who act blindly without ever trying to understand what went wrong.
Shipping software is uncomfortable because it exposes your work to the world, but with the right mindset, that discomfort becomes a powerful engine for progress.
Let Uncertainty Guide You