Tracking Progress Without the Pressure of Goals
It's natural to wonder whether you're actually improving as a programmer. The usual advice is simple: set goals, check your progress, and celebrate when you hit them. That approach works for some people, but it can also become a source of stress rather than motivation.
The problem with goals is that they tend to be inflexible. You might set a goal that made sense years ago, only to realize later that it was never something you truly needed. A goal like "learn C++" can linger for a decade, making you feel like a failure even though you never had a real reason to pursue it in the first place. You didn't fail; your priorities changed—but the goal didn't, so it sits there judging you.
Thinking in Terms of Milestones Instead
A more useful framing is to think in terms of tiny milestones. Not the kind of milestone that happens every few years, like graduating from university, but the original meaning of the word: stones placed every mile along a road so you can see your progress as you travel. These happen far more often—using a new tool, fixing a type of bug you've never seen, or finally understanding a concept that once confused you.
Consider a long-standing ambition like learning C. If measured against a single goal, it might look like nine years of failure. But broken into milestones, that same period can look quite different:
- wrote a tiny Linux kernel module that does almost nothing
- learned about
strace - wrote a very basic shell in C with a friend
- learned how ELF binaries are organized (symbols, sections, etc.)
- learned how to use
gdbto inspect a C program's memory - learned the difference between static and dynamic linking
- got a core dump from a crashing C++ program and pulled a stack trace out of it
- learned about the RAII pattern in Rust
- implemented a buffer overflow exploit for a CTF using
gdbandstrace
Individually, each of these milestones took less than a week. Together, they represent years of steady growth in systems programming—just not in the form the original goal envisioned. When viewed this way, there's a real sense of accomplishment, even without ticking off "learn C++."
Bugs Can Be Milestones Too
Every time you solve a bug you couldn't have solved before, that's a tiny milestone. The key is to resist the urge to look for a workaround and instead dig into the root cause.
For someone working on CSS skills, a recurring flexbox issue might feel like proof that the concept just isn't clicking. But taking the time to understand why the layout breaks—rather than patching around it—can be the breakthrough that turns a vague frustration into genuine knowledge. Finding a detailed explanation of the underlying behavior transforms a mystery into a lesson.
Goals Should Be Flexible
Not learning C doesn't mean you're bad at programming or that C is impossibly hard. It might simply mean that writing C well was never something you actually needed to do. Instead, time can be spent learning Rust, Go, gdb, the structure of binaries, the call stack, or the heap—all topics that arose naturally from real projects and real problems.
That is a healthier approach: be flexible about goals and celebrate the milestones you actually reach, rather than lamenting the ones you didn't. Most tiny milestones aren't planned explicitly—they happen along the way because you keep taking on projects that challenge you and bugs that force you to learn something new.
Make Milestones Worth Celebrating
It's important to acknowledge these achievements somewhere. Some people write blog posts about their tiny milestones. Others might maintain a brag document—a running list of accomplishments and things learned. Whatever the method, recording milestones provides a concrete sense of progress and helps sustain motivation over the long haul. That reinforcement is what keeps you curious and moving forward, one small stone at a time.



