Why I'm a hands on CTO who still writes code daily: how staying technical keeps engineering judgment sharp, the three kinds of code to write, and when to stop.
A recruiter once told me, as a compliment, that I'd "graduated out of the code." Six hours later I was shipping a fix to our auth flow at midnight, because nobody else on the team had enough context to do it safely — and I remember thinking his compliment was actually a diagnosis of everything that goes wrong with CTOs.
I'm a CTO. I lead a small engineering team at a startup in Dubai, six-plus years of building and shipping behind me. And I still open my editor almost every day. Not because I can't let go, and not because I'm hovering over my engineers' shoulders. I do it because staying technical is a resource-allocation decision, and I've done the math. This post is the math — the explicit rules I use to decide which code is worth my hands and which code I should keep them off of. If you're an engineering leader wondering whether a hands-on CTO is a relic or a requirement, this is the framework I'd hand you.
There's a story engineers get told on the way up. Individual contributor, then senior, then lead, then engineering manager, then director — and somewhere around "lead" you're supposed to quietly stop writing code, because writing code is a junior activity and your job now is people. The org chart becomes a ladder out of the thing you were good at.
It's a comforting story because it gives you permission to stop doing the hard part. But it's mostly wrong for the stage I'm at, and I suspect it's wrong for most people who repeat it.
The confusion is that people bundle two very different things under "staying technical":
The myth collapses those two into one and tells you to drop both. Drop the first, keep the second. That distinction is the whole post. A hands-on CTO isn't someone who refuses to delegate — it's someone who keeps their technical judgment calibrated on purpose.
The argument for going fully hands-off sounds responsible: your time is worth more spent on strategy, hiring, and unblocking others. Some of that is true. But there's a cost nobody puts on the invoice, and it compounds quietly until one day you're an expensive person who can't tell whether an estimate is honest.
Here's what erodes, in the order I've watched it happen:
The through-line: staying technical isn't about output. It's about keeping your judgment calibrated. Judgment is the actual product a CTO ships, and code is how you keep the instrument tuned. Every hour I spend in the editor is really an investment in the quality of the hundred decisions I'll make that week without touching a keyboard.
I think of my week as a budget with a hard cap. I get roughly 45 focused hours. My default assumption is that leadership work — hiring, one-on-ones, planning, unblocking, the stuff only I can do — will happily expand to consume all 45 if I let it. It's Parkinson's law wearing a suit.
So I don't leave hands-on time as a residual. Residual time is always zero. I carve it out first, treat it as a fixed cost, and let the leadership work fit into what remains. This is the single most important idea in the post: hands-on time is a fixed cost you pay first, not the slack you spend if any is left over.
My rough allocation looks like this:
| Bucket | Share of week | What lives here |
| --- | --- | --- |
| People and direction | ~55% | 1:1s, hiring, roadmap, cross-team, stakeholders |
| Deep technical work (hands on keyboard) | ~15% | The three kinds of code below |
| Reading code and reviews | ~15% | PRs, design docs, incident post-mortems |
| Slack, buffer, the unplannable | ~15% | Fires, context switching, the stuff that just happens |
Fifteen percent hands-on is about six or seven hours. That's not enough to be a load-bearing contributor, and that's the point. It's enough to stay fluent. The failure mode I'm guarding against is letting that number silently drift to zero, because the day it hits zero is the day my judgment starts its slow decay and nobody tells me.
These percentages aren't a prescription — they're mine, at my company's stage. If you run a 40-person org, your hands-on number is probably lower and your "system that produces the code" number is higher. The discipline transfers even when the ratio doesn't: name the buckets, defend the technical one first, and audit it honestly.
The trade I make consciously: I am slower at the code I do touch than my senior engineers are, because I'm out of the codebase more than they are. I've made peace with that. I'm not there to be the fastest. I'm there to stay calibrated.
Not all code is worth my hands. Most of it isn't — if I'm writing a CRUD screen, something has gone wrong with how I'm spending myself. I have exactly three categories where I still put my name on the commit. If a task doesn't fit one of these three, it's a signal that I should be delegating it, not doing it.
When we're evaluating something genuinely new and risky — a new payment provider, a shift in our data model, whether a feature is even feasible on our stack — I'll often write the throwaway prototype myself. Not because I'm the best person to build the real thing. Because the person who does the spike walks away with the sharpest possible understanding of the risk, and I want that understanding to live in the CTO, not to be summarized to me third-hand through two layers of "it should be fine."
A spike is a research instrument, not a deliverable. Its constraints are the opposite of production code: no tests, no error handling, no abstractions, no code review. The only thing it has to do is answer one question, honestly and fast.
// A spike is allowed to be ugly. Its only job is to answer one question.// Question: can we reconcile provider webhooks against our ledger// without a nightly batch job? Answer in code, then throw the code away.Future<ReconciliationResult> spikeReconcile( List<ProviderEvent> events, Ledger ledger,) async { final mismatches = <String>[]; for (final e in events) { final entry = ledger.lookup(e.reference); if (entry == null || entry.amount != e.amount) { mismatches.add(e.reference); // the answer I actually care about } } return ReconciliationResult(total: events.length, drift: mismatches);}I delete these. The value was never the code — it was the hour I spent learning exactly where the sharp edges are. Now when an engineer tells me reconciliation is a two-day job, I know whether that's true. A spike I keep is a spike that quietly becomes load-bearing production code with none of the rigor, so I'm ruthless about throwing them away.
Some code is dangerous in a way that maps directly to things a CTO is accountable for: authentication, permission and authorization checks, money movement, the security boundary, data-deletion paths. When the blast radius of a bug is "we leak user data" or "we double-charge a customer," I want to have my hands in that logic, at minimum as a co-author and reviewer of record.
This isn't distrust of my team. It's that the accountability is genuinely mine, and I refuse to be accountable for code I don't understand at the line level. On a recent project we tightened a Firestore security rule that was quietly allowing a read path it shouldn't. I didn't write the whole feature — but I wrote and tested that rule myself, because if it's wrong, it's my name on the incident.
// Firestore security rules are a perfect example of high-blast-radius code:// small surface, catastrophic if wrong, and easy to get subtly backwards.match /orders/{orderId} { // A user may only read their own orders. One missing clause here // is the difference between "correct" and "everyone reads everything". allow read: if request.auth != null && request.auth.uid == resource.data.ownerId; allow write: if false; // writes go through the backend only}The pattern to notice: this code is tiny, but the cost of getting it wrong is unbounded. That ratio — small surface, huge blast radius — is exactly the profile of work where a CTO's hands are well spent. It's high-leverage precisely because it's high-stakes and low-volume.
The third category is the small, boring tooling that makes the whole team faster: a flaky CI step, a slow local build, a script that turns a 20-minute manual release into one command. Unglamorous, nobody's promotion depends on it, so it rots in the backlog forever.
It's also perfect for a CTO. High-leverage (it multiplies everyone's time), low blast radius (if my release script breaks, we notice immediately and nobody's data is at stake), and it makes me feel the exact friction my engineers feel every day. When our CI was taking eleven minutes on every push, I spent an afternoon and got it to four. That afternoon paid for itself in a week — and every push after that is a small, permanent dividend paid to the whole team.
Developer experience work has a property I love as a leader: it's where I personally feel the papercuts my team is too busy to complain about. You cannot fix friction you don't feel, and this category keeps me feeling it.
Writing code keeps me fluent. Reading code is how I actually lead. And I read far more than I write — I'd guess a 3-to-1 ratio. If you take one habit from this post, make it this one: it's the highest-signal, lowest-cost thing a technical leader can do.
I don't mean rubber-stamping PRs. I mean deliberately pulling up parts of the system I have no intention of ever modifying, and reading them the way you'd read a report from a region you're responsible for.
Reading code is the cheapest, highest-signal way I have to know what's really happening in my own engineering org. It scales in a way that writing never will — I can read ten engineers' output in the time it takes to write a fraction of one engineer's.
This is the real danger, and I've felt its pull. The moment a technical CTO's involvement becomes required for things to ship, you've traded one failure for a worse one. Now the whole team is throttled by your calendar. A hands-on CTO who is also a bottleneck is worse than a hands-off one, because at least the hands-off one isn't blocking the release.
The rules I hold myself to:
The goal is to be a multiplier who happens to write code, never a dependency who happens to have a title.
I'd be selling you a comfortable story if I pretended hands-on time is always right. It isn't, and knowing when to drop it is part of the same resource-allocation discipline. The whole point of treating hands-on time as a budget line is that budgets get cut when priorities change.
I put the editor down when:
Staying technical is a tool, not an identity. The identity trap — "I'm an engineer, so I must be coding" — is exactly the ego I'm trying to keep out of the decision. The right amount of hands-on time is whatever keeps my judgment sharp without stealing hours the company needs elsewhere. Some quarters that's fifteen percent. Some quarters it's honestly closer to zero, and that has to be okay.
Rules are useless without a place on the calendar. Here's the actual rhythm I run, roughly:
The point of the cadence isn't rigidity. It's that hands-on time is now a scheduled fixed cost, not something I do if there's slack. There is never slack. If it isn't on the calendar, it doesn't happen, and then one day I'm the recruiter's version of a "real leader" who can't tell an honest estimate from a fairy tale.