From writing code to leading through others
November 2026 · Tomasz Borys
One thing I missed when I started moving away from writing code was the immediate satisfaction.
You have a problem. You investigate it, try something, run the tests and eventually see it working. Sometimes it takes hours, sometimes days, especially when you're figuring it out on your own. But when it works, you know it came from something you just did.
As my role moved towards technical leadership, that feeling became less frequent.
I was still solving problems, just not always by writing the code myself. More often, I needed to help other engineers solve them. And I discovered that the reward could take much longer to arrive.
Sometimes it didn't arrive at all.
Building something others could own
I remember this shift particularly well from our work on a shared testing capability. We were trying to test complete customer journeys, from registration and login through deposits, navigating the application and playing games.
The difficulty was that these journeys crossed boundaries between teams. Each team understood its own part of the application, but no single team owned the entire customer experience.
Together with other engineers, we established the foundation of a testing framework that teams could build upon. Rather than asking everyone to create separate frameworks, the idea was to let teams develop and maintain their own modules. Those modules could be reused for tests within their area and combined to verify journeys across the wider product.
Technically, I found that work exciting. I spoke about it at SauceCon in 2018, and the recording is still online.
But getting the framework working was only one part of the problem.
Just because something works doesn't mean people will use it
Some teams welcomed the approach. Others were less convinced. There were existing priorities, different practices and limited time in backlogs to contribute to something shared.
And there was another problem: trust.
The tests could be well designed, but if the surrounding environment wasn't stable, engineers couldn't always trust the results. When a test failed, was it exposing a problem with the product? Was there a problem in the test? Or had something in the environment changed?
Some people were happy to investigate. Others preferred to disable the tests and continue with their work.
I could understand the frustration.
We had created the basis for something useful, but its value depended on other people choosing to adopt it, maintain it and believe in it.
That required a different kind of work.
More conversations. More explanations. More patience.
It wasn't enough to hand over a working solution.
I supported developers and QA by showing where the tests had exposed issues in their own codebases. The value was in catching problems earlier in the delivery pipeline.
A different kind of satisfaction
There wasn't one big moment when it all clicked.
At first, people started asking questions. Then things began to work for them and they could see the value for themselves. Engineers developed their own modules and built on what we had established together. Later, I saw them teaching other members of their teams.
What stayed with me was watching them become confident enough to take it further and pass that knowledge on.
It was a different reward from seeing my own code working. It took longer and depended on other people. But when it worked, it could feel even better.
The part I found harder
There was another side to this transition.
As I became involved in larger architectural decisions, I couldn't follow every implementation detail as closely as I used to. I was working on the direction of applications, their configuration and how technology decisions supported longer term business needs.
Meanwhile, individual teams were making decisions in the context of their own codebases. That was necessary. They had knowledge I didn't always have.
But occasionally, during discussions about larger features or when investigating inconsistent behaviour, I discovered that different parts of the product had evolved in ways I hadn't expected. Something that appeared to be the same feature to a customer could behave differently across platforms.
Part of it was my own assumptions. If two client apps supported the same customer journey, I expected them to behave alike. If a bug appeared on one platform, I sometimes expected to see it on the other too. But a timing issue could affect one app and not another because each had been built differently. Knowing the direction we were heading didn't mean I knew how each app actually behaved.
The implementation languages and platform constraints were different, naturally. But some differences went beyond the technology itself. I remember being surprised when we needed to revisit how session and cookie behaviour worked across applications.
It wasn't a question of someone doing a bad job. The teams had made decisions based on their understanding of the problem. I had a broader architectural direction in mind. Somewhere between those two views, we had missed an opportunity to align.
My immediate reaction wasn't that I had failed, or that I needed to take control of the implementation. It was that I needed to understand their context better.
We had to go back to the drawing board, look at what each application was actually doing and work through how the different parts should fit together. Then I needed to communicate the architectural direction in a way that made sense to the engineers working in those codebases.
That was harder than simply deciding how I would implement something myself.
I wrote about a similar gap in my earlier article on distributed systems: code shows only part of the picture, and the rest lives in runtime behaviour and in what people across teams know. That time I was investigating a system. This time the gap was in my own picture of what the teams had built.
Letting go without disconnecting
I don't think technical leadership means stepping away from the technical details altogether.
I still want to understand how systems work. I still enjoy investigating difficult problems. And I still think it matters to be able to challenge implementation choices.
AI has become part of how I do that. With coding agents I can explore an unfamiliar codebase, follow a dependency across services or work out why something behaves unexpectedly, without first spending days reading code and documentation on my own. It helps me rebuild context quickly enough to ask better questions.
It doesn't understand the system for me, though. In that distributed systems investigation the code only took me so far. The rest came from runtime evidence and from the engineers who knew how their part actually behaved.
But I no longer expect to know every decision being made.
Instead, the challenge is recognising which decisions matter beyond one team, helping engineers understand the wider context and making sure important differences become visible early enough to discuss them.
That doesn't mean every team must build everything in exactly the same way. It means we should understand when differences are intentional, when they are necessary and when they are simply the result of people working without enough shared context.
I'm still learning how to get that balance right.
What changed for me
Now, I might spend hours explaining an idea, helping a team understand a problem or connecting people who have different pieces of the answer. I may not see what comes of that work for weeks or months.
Sometimes people take the idea further than I expected. Sometimes they choose a different approach. Sometimes the work doesn't happen at all.
I've had to become comfortable with that uncertainty.
AI is changing how I approach implementation too. I still get involved in building and changing applications, often working with coding agents.
What interests me now is how we verify their work. Some things can be checked precisely through code and automated tests. Others need room for an agent to investigate, reason and assess the evidence. I'm exploring how to combine both approaches without losing responsibility for the result.
Agents can also reuse skills and knowledge we give them. But that's different from seeing another engineer grow in confidence, develop their own understanding and eventually teach someone else.
What I didn't expect was how satisfying it could become to see other engineers take something forward without me.
The code is no longer always the thing I deliver.
Sometimes the most valuable thing I can do is help other people build something better than I could have built alone.
My thoughts, captured through dictation and interviews. Structured and edited with AI.