So far, I’ve explored technical bottlenecks in the development process. In this post I want to talk about people bottlenecks. In particular, I want to talk about the team.
So, you’re working in small batches and micro feedback loops, solving one problem at a time. You’re testing continuously. You’re reviewing code continuously. You’re integrating continuously.
But are you making the decisions when they need to be made? Or are you waiting for permission from above?
Lack of autonomy, perhaps as a result of a lack of trust in the team, can create serious bottlenecks in the development process. The less decision-making power teams – and individuals on teams – have, the more decisions have to be sent up the chain of command, and potentially the longer we have to wait for a thumbs-up.
It’s just another queue. (And if the boss is one of those whose diary’s blocked out for the next 3 months, probably a very long queue.)
Just as we can reduce bottlenecks in testing or code review by doing it as the code’s being written, we can reduce bottlenecks in decision-making by making them when a decision’s needed. And that means making the decisions ourselves a lot of the time.
Managers who are prepared to relinquish day-to-day control and let teams just get on with it are sadly not the norm. Sometimes that’s down to a lack of trust that a team can be left to get on with it. (And, to be fair, the team may have earned that mistrust through past disappointments).
It can be a vicious circle: to earn trust and gain autonomy, teams need to deliver consistently and reliably. To deliver consistently and reliably, teams require a significant amount of autonomy.
My party trick as a contractor was to break the cycle, and I did it many times. If autonomy wouldn’t be given freely, as the lead developer, I would take it.
The team then has to put up or shut up, of course. There’s a window of opportunity to get the train moving, and to be seen to be moving. Changes have to happen fast. Look for low-hanging fruit!
That takes some nerve, though. It’s not in everybody’s comfort zone. (I remember being pulled aside by a team member and accused of “setting out to succeed” when we should be “covering our backsides” for when we inevitably fail. I don’t subscribe to that newsletter. I’m here to chew bubblegum and deliver software. And I’m all out of bubblegum.)
Once a consistent pattern of drama-free delivery’s been established, management will tend to back off. (Not always, of course – for some, it really is about control. But that’s a whole other series of posts.)
But the reality is inescapable. If the team doesn’t have sufficient autonomy, that will create bottlenecks in decision-making. I know. It’s so unfair!
The make-up of the team can also create bottlenecks. Over-specialised teams (the “front-end” team, the “back-end” team, the testing team, the “DevOps” team – an oxymoron if ever I saw one) will likely spend a lot of time waiting on other teams.
Organising teams around specific skillsets or technology areas suffers the same consequences as organising our code that way – the “UI layer”, the “services” layer, the “business logic” layer etc.

It ends up creating networks of teams that are tightly coupled to each other. To deliver anything end-to-end requires lots of inter-team communication and coordination, making business outcomes an order of magnitude harder to achieve.
Again, it’s about architecture – coupling and cohesion. Instead of “front-end”, “back-end”, “data” etc, how about the “Mortgage Applications” team, that encapsulates – as much as possible – the skills needed to deliver Mortgage Application functionality end-to-end?

Front-end, back-end, DB, ops, architecture, testing, security, UX design – these can simultaneously become internal communities of practice, if they’re given the time and the space to meet and to share ideas. This would be part of the 20-25% of the total dev budget that organisations need to invest to build long-term capability.
And even when we have cohesive, loosely-coupled teams organised around business outcomes, there’s still much potential for bottlenecks inside the team if members themselves are over-specialised.
If a team of 6 – a nice manageable number for communication – has one testing specialist, and nobody else on the team knows anything about software testing, then there’s going to be a queue forming for their services. That’s not conducive to testing as we code.
Flipping that around, if the testing specialist has no programming skills, they’re going to be waiting for someone to automate their tests. Either that, or the team relies entirely on manual regression testing.
Either way, the testing bottleneck is back!
If everybody on the team had some foundational testing and programming skills – the 20% we might need 80% of the time – then this bottleneck can be minimised. Team members may need to call on the expertise of a testing guru, perhaps inviting them to pair on an serious testing problem, but now one testing specialist may be enough for 5 programmers.
Developers who have deep expertise in one or two disciplines or technologies, but have a practical foundational grasp of others, are often referred to as “T-shaped”, or “generalising specialists”.
It takes quite a lot of experience and ongoing learning to become genuinely T-shaped, which is why T-shaped developers tend to have been working in software in a hands-on capacity for a decade or more.
(That’s not to say, of course, that every developer with a decade or more’s experience is T-shaped. There are plenty who’ve had “1 years’ experience 10 times”.)
The implication for team make-up is that it will be skewed towards more experienced people. Many managers endorse a diamond-shaped distribution of experience on a team, with maybe one very experienced lead or principal developer, a whole bunch of “mid-level” or “journeyman” developers, and maybe one or two junior trainees to maintain a healthy talent pipeline.
I, on the other hand, recommend an upside-down pyramid, with the bulk of the developers being very experienced and T-shaped, and with a narrower pipeline feeding up to that. An aging population, if you like.
And the implication of that is that teams are long-lived, and that the most skilled and experienced developers – regardless of their specialisms – stay developers.
Now, some of you may be thinking “But I don’t need to understand X, Y or Z, because Claude or GPT-5 can fill in those gaps for me.”
And it’s certainly true that hyperscale LLMs will have a lot of knowledge about other disciplines in its training data. But, as I’ve argued much in this series, they don’t understand and they don’t think. So how that vast knowledge might be applied on real-world problems would, for me, be a genuine worry.
It may look plausible to my untrained eyes, but… Be wary of falling prey to the Gell-Mann Amnesia effect.
And I don’t think testers, architects, operations, product managers, security experts and others would be too happy to learn we don’t think what they do requires Actual Intelligence, just as we can be offended when people imply the same about us.





