devShakib

Loading devShakib…

I'm a CTO Who Still Opens the Editor Every Day

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.

The myth that technical leadership means leaving the codebase

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.

What you actually lose when you stop shipping code

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:

  1. Your estimates go soft. When you haven't touched the code in a year, you lose the texture of how long things actually take. You start accepting "two weeks" for things that are two days and "two days" for things that are a hidden two-month migration. You can't feel the difference anymore — and estimation accuracy is one of the most valuable things a technical leader brings to a planning meeting.
  2. You stop being able to smell bad architecture. Good technical judgment is mostly pattern-matching on pain you've personally felt. Reading a design doc is not the same as being the one who has to live in the system it describes. The nose dulls fast, and architectural mistakes are the most expensive kind to unwind.
  3. You lose the trust of your best engineers. Strong engineers can tell within one conversation whether you understand the thing you're making decisions about. The moment they conclude you don't, they route around you. Politely. And now you're leading people who've quietly decided your technical input is noise. Technical credibility is not a title you're granted — it's a thing you re-earn in every architecture review.
  4. You become a hostage to consensus. When you can't independently evaluate a claim, every technical debate resolves by whoever is most confident or most senior in the room. That's a terrible way to make architecture decisions, and it's exactly where you end up when your own read of the code has gone stale.

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.

My technical budget: the hours I protect and the ones I trade away

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:

BucketShare of weekWhat 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.

The three kinds of code a CTO should still write

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.

1. Spikes into the unknown

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.

2. The load-bearing, high-blast-radius core

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.

3. Developer-experience and tooling glue

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.

Reading code you'll never touch is a leadership tool

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.

How I avoid becoming the bottleneck I'm trying to prevent

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:

  1. I am never on the critical path by default. If a feature can't ship without my code or my review, that's a bug in how we've organized, not a fact of nature. My hands-on work goes into things that are important but not time-boxed to a release — spikes, tooling, hardening. When I do touch release-critical code, it's a deliberate exception, and I say so out loud.
  2. I write to be deleted or handed off. Spikes get thrown away. Core code I write gets a second owner immediately — I pair on it or hand it over so I'm never the only person who understands it. If I'm the bus factor, I've failed. Every commit I make should have a plan for how it survives without me.
  3. My reviews are optional, not blocking. I comment on a lot of PRs. Almost none of them require my approval to merge. I want my input to be available, not mandatory. The team should be able to ship at full speed on a week when I'm heads-down on hiring.
  4. I track a simple metric: can they ship without me? The honest test is a vacation. If the team's velocity drops when I'm gone, I've made myself load-bearing and I need to unwind it. If it doesn't drop, my technical involvement is additive, which is exactly where I want it.

The goal is to be a multiplier who happens to write code, never a dependency who happens to have a title.

When staying technical is the wrong call

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.

A weekly cadence that keeps my hands and my head in the work

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.

Key takeaways