Throughout my career as a software engineering manager, I have built a metaphorical toolbox containing methods and techniques for building strong, compassionate, and productive teams. One of the key tools is assigning engineers joint accountability to projects. For significant features or changes, I ensure that two people are accountable for delivery, quality, communication, and success of the work. This has numerous benefits and has become a critical tool in managing remote teams.
Assigning joint accountability with proper guidance and training leads to higher quality code, greater team cohesiveness, more engaged engineers, better interpersonal awareness (EQ), and higher productivity.
I landed on this concept as an avid pair programmer and built on it while running teams for years. I experimented with many techniques and learned where pair programming worked well and where it didn’t. I learned about different personality types and how individuals react based on the type of work and deadlines. My experiences led me to shift from an ideological position of “pair programming for all” to my implementation of joint accountability. Joint accountability is a way to get the benefits of pair programming but in a more flexible and general way.
Starting off with pair programming
Shortly after I joined Microsoft out of college, I landed on a team that practiced pair programming. The concept petrified me. Pair Programming is the development technique where two engineers work together at one workstation (physical or virtual). One engineer is typing while the other one observes, discusses, comments, and directs. As a young engineer with a ton of imposter syndrome, I had many thoughts when I first pair programmed:
- You mean someone is going to watch me …. type?
- What if they realize I am a fraud?
- What if it turns out everyone is just way better than me?
I was paired up with one of the most senior and confident engineers on the team. This developer was diving into an area of the code and typing while I was asking questions. I remember clearly pointing out some issue with what he just wrote. He paused typing, thought for a minute, and said, “great catch”. He fixed the issue and we moved on.
The thing that surprised me with the pairing experience was that it wasn’t just about “training the new guy”. It was about higher code quality and ensuring the team had a common baseline understanding of the whole codebase. Even as the brand-new team member, I was expected to contribute and learn while pairing. I soon understood that everyone I paired with expected me to pull my weight regardless of my experience. There was a deep trust between pair partners, and you wanted to live up to the trust given.
I worked on teams practicing pairing for 5 years and transitioned from the most junior to the most senior engineer on the team. All the while I was honing this craft and learning how it helped build a culture of quality and unity in the team.
When I eventually became an engineering manager years later, I knew I wanted to build a team that benefited from the performance and trust I experienced.
From ideology…
In researching development methodologies, you will quickly find lots of competing views and strong opinions; pair programming is no exception to this. I have talked to people who vehemently believe it is a waste of time, counter-productive, or just not the way they want to work. Similarly, I have spoken with people who argue you should always pair, and no task is not a good task to pair program on. In general, extreme stances that fail to consider nuance and trade-offs are most likely a gross oversimplification.
When I started as an engineering manager, I worked on a team and a group that did not pair program. I didn’t want to rock the boat and followed the processes the team already had for several months. However, we were struggling with knowledge silos leading to poor code reviews, work stoppages during individual engineer time-off due to lack of context, and a lack of team cohesion. When I asked my boss to let me try out pair programming (along with some other structural changes) with the team, she supported me (although with healthy skepticism). I proposed a 6-week pair programming experiment. After this period the team would decide if we wanted to continue. The team accepted this proposal (with reservations) but initially it was turbulent. The engineers weren’t used to working together and some didn’t know how to communicate 1×1 while coding. I actively coached and found a few engineers who immediately showed great skill at the practice. I leveraged them as a vanguard to pair with others and help train and teach how to pair effectively.
By the end of the 6 weeks the culture and environment had evolved, and team chemistry was growing. At our retrospective the team agreed to keep working this way. We were more aware of the work the entire team was doing, enjoying the work more and delivering higher quality code.
However, it was not all sunshine and rainbows. Even while the team worked better, there were some engineers who clearly preferred not to pair. Sometimes engineers wanted to drive items individually to test themselves, or just wanted days of focused headphone music coding time. I listened to the reservations and found ways to balance and flex the model to work through it with them. But this left me questioning what is the key to the growth and benefits we saw? Is it truly two programmers one keyboard? Or is there another way to get these benefits in a more general and systematic way where?
…To pragmatism
After years of running that team successfully with pair programming as a core tenet I decided to change teams and move to a group in Azure. During this transition my key concern was how well my existing toolbox would work in a new team, environment, and problem space. After joining, I noticed many of the same problems: Silos, lack of group culture (was more individualistic), interpersonal conflicts and lower quality deliverables than they were capable of (the team was very talented). At this point I thought this was perfect, I already had a tool to solve this and proposed pair programming as part of the team methodology but got significantly more pushback than before.
This forced me to think hard about what I was trying to accomplish. Was my goal that everyone pair program or was it actually to inculcate a culture of trust and quality? This led towards refining pair programming into a new model for this team. I proposed to the team an experiment called active/passive pair programming. The idea was that we prefer to have pairs own deliverables, but the pair decides at the start of the work which parts need “active” pairing (two engineers working directly together at one keyboard) and which parts will use “passive” pairing (they work on different independent parts but check in multiple times a day).
My fear in this tweak was that it would devolve into fully independent work streams, and we would return to silos and lack of unity across the team. To prevent this, I highly encouraged pairs to try “active” pairing at least once a day and to routinely check-in with each other multiple times a day while “passive” pairing. Even while passive pairing, I made clear that both individuals must have full context on the work.
Some engineers actively paired, but many of them did passive pairing. I saw similar results as those in my previous experiment. The team grew closer together, psychological safety increased, and we were able to deliver more with higher quality. Even while passive pairing, the pairs communicated more, got to know each other and learned to rely on each other for questions and feedback.
The Power of Joint Accountability
When I left Microsoft to join Palmetto Solar, I transitioned into my first remote only role as a manager. I started this job with a renewed concern of how to build the culture I have seen work multiple times in an environment when we are seldom in the same physical place. Building trust, cohesiveness, minimizing silos, and creating a psychological safe environment are the keys but would the same techniques work remotely?
Reflecting on the success of the passive/active pairing experiment, I realized the reason it worked was trust. I extended to the pair the trust of accountability. They were accountable for how they worked, and for the success of the feature. By placing the accountability on them as a pair, it encouraged the behavior I was looking for. That is how I landed on the latest iteration of this technique which is to assign joint accountability on significant deliverables.
When planning new work streams, I ask the team who is interested in the work, and then we decide on a pair of engineers to take on joint accountability for the feature’s success. This is not just getting the feature out the door, but the entire lifecycle: design, coding, review, telemetry, and deployment. I don’t require that they “actively” pair at all (although many do). I make clear that I expect both people to have full context on the work. If one is out on vacation, the other can support and continue the other person’s part. If there is a question from a stakeholder, product manager, or other engineer, each person in the pair must be able to handle it.
Even in a remote only work environment, the pairs build close relationships driving features. Over time they learn each other’s communication styles, support each other, and even when not pairing, they end up with many calls to break down design issues and to act as rubber ducks for each other.
As new work comes, we rotate pair members to ensure different groupings work together. Over time this increases the cumulative level of trust, interpersonal awareness, and technical breadth within the team.
Critiques and Questions About Joint Accountability
Over the years of deploying versions of joint accountability I have heard feedback from peers and engineers. One concern I hear is around rewards, if a pair delivers a feature who gets credit? As long as both people have been driving impact to the best of their ability, they both deserve acknowledgement for the success of the feature. If the pair was not functioning well and one member feels they did most the work, it leads to the other concern I hear often, handling a non-functioning pairing.
There is a common concern that the stronger or more experienced engineer will carry the pair, and the other engineer just watches and does not contribute. In my experience though, this rarely happens, in most cases both people, even with a technical or experience gap, are eager to deliver value and contribute. However, I have witnessed a few times when one of the engineers clearly was not doing their work or seemed checked out.
In fact, this is actually a huge benefit of joint accountability – problems of this nature arise and become evident very quickly. When a pair is accountable for a feature, I periodically meet with each person individually. The focus is to provide coaching to make sure they are listening, questioning, and supporting each other well. In these meetings, I hear of any conflicts or roadblocks (which are natural when people are first learning someone’s communication style). Usually, if one person feels the other is not doing their fair share, I am able to provide coaching or more pointed, redirecting feedback if needed.
Keys to implementing Joint Accountability Successfully
If you are struggling with some of the same issues I faced, assigning joint accountability may help. To start, I recommend proposing it to the team as an experiment. All process changes work better when you get buy-in from the team and make clear their input is an integral part of the change. Set an expectation for the duration of the experiment and when and how often you will iterate and tweak. I use the team’s sprint retrospective for this purpose.
For joint accountability to work you must make crystal clear three key expectations:
- The pair is accountable for the entire lifecycle of the change/feature. From initial design and implementation to deployment, monitoring, documentation, and communication.
- Each member of the pair must have full context on all that is being built. If one member of the pair is out sick, the expectation is the other must be able to pick up their work if needed.
- The pair chooses how they work (pair programming, divide and conquer, etc.). Trust them to make this decision rather than dictating how they work. This trust is critical.
Once the team agrees to try this experiment and all understand the expectations, you are ready to see if it starts the journey to a stronger more cohesive team. As work progresses, hold 1x1s with each person and ask how things are going. Checking in is not solely about the status of the work, but the status of their communication and how well they are listening and relying on each other. Look for issues, communication gaps, or dissonance as opportunities to coach and guide.
Closing Thoughts
Joint accountability is a flexible and powerful way to build a team that has more trust, autonomy, and accountability. In my experience it has been a critical tool in constructing strong teams. But like any process, it may not work in all situations or for all people. The key is to listen, take feedback and make sure you are focused on the end results and not married to any specific process or methodology.