You're Getting Better at the Wrong Thing
After 25 years, I'm convinced the craft problem and the character problem are the same problem.
Early in my career, I watched a developer do something I’ve never forgotten.
He inherited a codebase that was, by any honest measure, a mess. Years of rushed deadlines, mid-sprint requirement changes, and the particular brand of creative improvisation that happens when good developers are under constant pressure. The kind of code that tells a story. Not a flattering one, but a real one.
He was talented. Genuinely good. And he was furious.
Within a week, he had decided to rewrite the entire e-commerce system from scratch. The right way, this time. Clean architecture. Proper separation of concerns. The kind of code you’d be proud to show in an interview. He was meticulous about it. He worked longer hours than anyone on the team. He was, in his own estimation, fixing what was broken.
What he actually did was break what was working.
The original system, for all its ugliness, had accumulated years of edge case handling. Weird discount logic that reflected real customer behavior. Payment processing quirks specific to their merchant processor. The kind of institutional memory that doesn’t live in documentation, it lives in code that’s been in production long enough to absorb the real world.
His rewrite was architecturally beautiful and practically broken. It took months to untangle.
When I think about that developer now, what strikes me isn’t the technical failure. The technical failure was just the outcome. What strikes me is what he never saw: that his internal state was doing the work. He thought he was making an engineering decision. He was executing an emotional one. The system he shipped was organized by anger, and it looked clean, and it didn’t work.
He treated it as a technical problem. It wasn’t.
In 25 years, I have watched that pattern in a hundred forms. The developer who can’t hear feedback because their certainty is load-bearing. The architect who solves every problem with another abstraction layer because abstraction feels like intelligence. The senior engineer who stopped learning at year seven and mistakes comfort for mastery. Different symptoms. Same root.
The root isn’t technical. It never was.
The Wrong Question
Most developers spend their careers asking one question: how do I get better at this?
It’s a good question. It has real answers. Deliberate practice on hard problems. Working alongside people who are better than you. Reading widely, not just documentation, but systems, histories, postmortems. Staying curious about the craft itself, not just the tools. These things work. They produce competent developers.
They don’t produce wise ones.
The technical question optimizes for a specific kind of output. You get faster. You accumulate patterns. You build intuitions about architecture, about performance, about where bugs tend to hide. All of that matters. All of that is real.
But past the journeyman stage, and you reach that stage earlier than you think, more of the same returns less. The developer who grinds harder on the technical question past that inflection point isn’t getting sharper. They’re just staying busy. They’re adding syntax to a foundation that isn’t the problem.
The developers who don’t plateau, don’t burn out, don’t lose the plot at year twelve, they found a different question. Not consciously, for the most part. Nobody sat them down and assigned it. But somewhere along the way, they started asking something else.
The question isn’t how do I get better at code?
It’s what kind of developer am I becoming through this work?
That sounds like a soft question. It isn’t. It’s harder than any technical problem you’ll face, because it has no Stack Overflow answer and no framework that solves it for you. And ignoring it, which most developers do, because the technical question is so much more tractable, doesn’t make it go away. It just means the answer accumulates silently, in the background, until you’re that developer rewriting working systems out of ego and calling it engineering.
What Stoicism Actually Is
I want to be direct about something before going further, because this is where people tend to check out.
Stoicism has a branding problem. Most of what circulates under that name is a thin self-help product: control what you can control, don’t sweat the rest. It’s not wrong, exactly. But it’s the philosophy stripped of everything that makes it worth practicing. It’s the bumper sticker without the argument.
The actual practice has real load-bearing pieces, and three of them apply to software development with uncomfortable precision.
The first is what Epictetus called prosoche: a sustained, disciplined attention to your own internal state. Not a journaling practice. Not meditation, though those can serve it. The actual discipline of noticing, in real time, what is happening inside you before it becomes behavior. The anger before it becomes a rage rewrite. The anxiety before it becomes an architectural decision made from fear. The certainty before it calcifies into an inability to hear what someone is actually saying to you.
Marcus Aurelius’s Meditations are, essentially, prosoche in written form. A daily record of a man watching himself think, catching his own patterns, trying to close the gap between his values and his behavior. He was the most powerful person on earth and he spent his mornings doing this work. That’s not incidental.
The second is askesis: what Seneca and Epictetus both described as voluntary discomfort, the deliberate choice to stay with what’s hard rather than reach for what’s easier. Not punishment, but training. You don’t stumble into deep competence by accident. You choose difficulty repeatedly, especially when you don’t feel like it, because the struggle is where the actual formation happens. Seneca recommended periodically living as if poor, not out of asceticism, but to prove to himself that what he feared losing wasn’t actually what sustained him. The principle scales: every time you skip the painful debugging session by asking someone else, every time you reach for an abstraction before you understand the concrete, you’re making a small choice against formation.
Those choices compound.
The third is the dichotomy of control. And I want to rescue this one from its bumper sticker version, because it’s a sorting tool, not a coping mechanism. Epictetus opens the Enchiridion with it for a reason: some things are up to us, some things are not, and wisdom begins with correctly sorting everything in your life into one of those two categories. The question isn’t how do I feel okay about things I can’t control? The question is where exactly is my sphere of genuine agency, and am I actually working there?
Most developers are working outside it constantly. Reacting to code someone else wrote as if it’s a personal affront. Anxious about market forces they cannot move. Performing competence for stakeholders who don’t understand what they do. That’s not bad character, it’s what happens when nobody gives you the sorting tool. The work is scattered across the uncontrollable, and it feels like effort, and it produces very little.
These three practices are two thousand years old. They were developed by people who had nothing like software in mind. They fit the specific conditions of software development. The uncertainty, the pace, the fragile ego that the industry somehow both produces and exploits, with an accuracy that still surprises me.
The Right Question
Go back to that developer and the e-commerce rewrite.
What he lacked wasn’t technical knowledge. He had more than enough of that. It was, in fact, his technical knowledge that made the failure possible. He could see clearly everything that was wrong with the original system. He had the skills to fix it. What he didn’t have was prosoche. The self-awareness to notice that his certainty about the right answer was being generated by his anger at the wrong one. His internal state was the variable. He never looked at it.
The right question, what kind of developer am I becoming through this work?, is a prosoche question. It requires watching yourself over time. Not in a self-absorbed way, but in the way that Marcus Aurelius watched himself: practically, unsparingly, with the goal of closing the gap between who you are and who your work requires you to be.
What does that actually look like at year five? At year fifteen? At year twenty-five?
At year five, the right question starts to reveal that technical skill is not the ceiling you thought it was. You’ve watched junior developers who are technically sharper than you produce worse outcomes, and you’re starting to understand why: they can’t hear feedback, they can’t operate in uncertainty, they can’t estimate honestly because their ego is on the line. You realize that you are also doing all of these things, just with more years behind you. The question starts to feel urgent.
At year fifteen, the right question sounds different. You’ve accumulated enough judgment to walk into an unfamiliar codebase and know, within an hour, where the real problems are. Not from technical inspection alone, from pattern recognition that lives somewhere below the explicit, built from thousands of situations where you paid attention to what was actually happening, not just to the code. You can hear a requirements meeting and catch what’s not being said. You can feel the moment a technical decision is actually a political one wearing technical clothing.
That capacity doesn’t come from solving more tickets. It comes from having practiced prosoche across thousands of decisions. Having paid attention to your own internal state often enough, honestly enough, that your read of a situation now includes what you’re bringing to it.
At year twenty-five, the question has become something close to habitual. You don’t ask it explicitly every day. But the practice of asking it, over decades, has changed what you notice and how quickly you notice it. You sit with a hard problem differently. Not with less uncertainty, with more comfort in uncertainty. The willingness to stay in the not-knowing until the actual shape of the problem becomes clear, rather than reaching for the nearest pattern that fits.
That capacity, to sit with a hard problem rather than execute the first solution that reduces the discomfort of not-knowing, is askesis applied. It is the compounding return on having practiced voluntary discomfort. You stay with what’s hard because you have trained yourself to stay with what’s hard, and staying has become less costly than it used to be.
Here’s what doesn’t produce this: solving more tickets. Accumulating more frameworks. Getting faster at the technical parts of the job. Those things are real and they matter, but they are not the thing.
The thing is philosophical. It has always been philosophical.
What Actually Compounds
Technical skill has genuine diminishing returns past the journeyman stage. This is observable. Every senior engineering team has watched it: the brilliant junior who peaks at year five because they stopped choosing difficulty. The mid-level developer running the same three architecture patterns on every problem because those patterns work and nothing hurts enough to require something new. The staff engineer who can solve any technical problem put in front of them and cannot, for the life of them, figure out why they feel irrelevant.
It’s not that their skills degraded. It’s that their skills stopped growing in the direction that matters, because they were still asking the first question (how do I get better at this?) long after the ceiling on that question became visible.
What compounds differently is judgment. And judgment, I want to be clear about what this actually is, is not instinct. It is not talent. It is not something you either have or don’t.
Judgment is developed attention, over time.
The developer at year fifteen who can walk into an unfamiliar codebase and feel, within an hour, where the bodies are buried. They’re not magic. They have been practicing prosoche. They have been paying disciplined attention to their own read of situations, to the patterns in their own perception, across thousands of instances. They’ve been getting fast at noticing what they’re noticing.
They will tell you they have good instincts. They don’t. They have something better: a calibrated relationship with their own attention, built through practice. The difference matters because instincts can’t be transferred and can’t be improved. Developed attention can be both.
The practical consequence: the questions that feel most important at year three, which framework should I learn, is this the right stack, am I behind?, are almost entirely technical questions with technical ceilings. They are worth answering. Answer them. And then start asking the question underneath them, before you reach year seven and find yourself wondering why the work that used to feel like growth now just feels like effort.
There is a version of a software career that is twenty-five years of accumulating syntax. And there is a version that is something else entirely. Something harder to name and much harder to acquire, because it requires a different kind of attention than the industry teaches you to pay.
The developers who figure out which version they’re building, early enough to do something about it, are not smarter. They found the right question sooner.
Where This Goes
Three practices. Not a philosophy lecture, three concrete things that take fifteen minutes each to learn and a career to get right.
The morning sequence: before the day’s first Slack notification, before the standup, before anything external has a claim on your attention, take fifteen minutes to set an intention grounded in what you actually value. Not what you need to ship. What kind of developer you want to be today. It sounds soft. It is structurally the most important fifteen minutes of the day, because everything else follows from what it surfaces.
The evening review: Seneca did this every night. He described it in De Ira: “I examine my entire day and go back over what I’ve done and said, hiding nothing from myself, passing nothing by.” Five questions. Where did I fall short? What went well? What was outside my control and am I still holding it anyway? What did I learn? What is my intention for tomorrow? Fifteen minutes. The compounding effect, over years, is not theoretical.
The Stoic pause: in the moment before you respond to the critical code review, the impossible deadline, the Slack message that made you feel what you felt, stop. Physically. Close the laptop screen. Apply the sorting tool: what here is actually in my control? Respond from there. It is the smallest practice and, in the daily conditions of developer work, the one with the most immediate return.
These are the frameworks I’ve built The Stoic Coder around. Not because Stoicism is the only lens on this, but because it’s a 2,000-year-old technology for exactly the problem I’ve spent 25 years watching developers fail to name: that the work is harder than the technical parts suggest, and the reason is philosophical, and there are actually answers.
You’re in the right place to find them.
Quote of the Day:
“First say to yourself what you would be; and then do what you have to do.” - Epictetus, Discourses
👉 If you enjoy reading this post, feel free to share it with friends!
Or feel free to click the ❤️ button on this post so more people can discover it on Substack 🙏
You can find me on X and Instagram.
Also, I just launched a new YouTube channel - Code & Composure


