My team at Entelect joined a client’s project three months after it started, and needed to catch up. We succeeded by overhauling our team structure, code review and development processes, and how we think about meetings. Here’s how we became a more efficient, self-managed team.
In February 2021, we joined forces with a company from the USA to develop a system for our client. They had already started with the backend and web application three months prior, and we were tasked with developing the mobile applications. Our main goal was to reach feature parity with the web application as quickly as possible.
We were constantly playing catch-up with the other contractor, and we had to improvise and adapt our way of working to reach our goal as quickly and efficiently as possible. Within the next year, we streamlined our day-to-day so well that we delivered at a faster rate and eventually took over the entire project from the much larger US-based team without increasing our team size.
How we set up our team to be self-managed
Our team consists of:
- a business analyst (BA)
- a quality assurance (QA) engineer
- a senior software engineer
- three intermediate software engineers
- a junior software engineer
We noticed over time that team members would naturally assume different roles in the project based on their experience and the project’s current needs. Rather than being assigned a position based on job title, these roles grow and fade organically based on what is necessary for the project at any given time. For example, our QA also functions as an Agile Coach, our BA actively participates in debugging sessions, and our lead code reviewer is not our most senior developer. We even have developers sometimes performing the role of a business analyst early in the ideation phase of a new feature instead of just waiting for the next thing to code.
Because these roles are fluid and we don’t have a designated team lead, we interface directly with our client.
By purposefully keeping the feedback loop between the client and us as small as possible, we become more invested in the product, can iterate faster and fewer things get lost in translation because no single person acts as a proxy between the team and the client.
This led to greater trust between the client and us and internally between our team members. Everyone in the team is considered equal and is privy to the same information. This, together with the lack of a fixed authority figure in team discussions, resulted in the perfect space for team members to voice their opinions and frustrations. Discussions and debates are rarely one-sided, and team members feel like what they say actually matters, which has a tangible effect on the project's success.
How we deal with team conflict
We have a manager, but he doesn’t take part in our day-to-day processes. Our manager doesn’t function as a traditional “team lead” but works in a broader, more procedural context. For example, he automatically approves leave requests because he trusts us to talk to each other and the client first. He also expects us to handle conflict within the team on our own as far as possible and only to escalate issues if they truly start to get out of hand.
A self-managed setup also poses particular challenges. Because its success depends on individual team members rather than a fixed hierarchy, it’s typically better suited for more senior or independent individuals. People with less independent personalities or little experience can find such a self-managed setup quite uncomfortable.
The entire team suffers if just one team member doesn’t pull their weight. Teams, therefore, need to be acutely aware of each other’s expectations and keep each other accountable at all times to avoid such situations as far as possible. And, in cases where the team cannot resolve conflict, you need a backup plan to address it as soon as possible.
In our team, we’re expected to let each other know if we feel someone else is performing in a way that negatively affects the rest of the group or the project. It shouldn’t only come up in a performance review.
We always first try to resolve conflict on an individual basis. When someone’s performance isn’t up to scratch, we mention it to the rest of the team. Then our BA or Senior Developer discusses the issue with the individual. As our BA spends the most time liaising with our client and our Senior Developer is the most senior person on the team, they naturally assumed these roles.
If that fails, we discuss the issue in our team retros where the focus is on the tasks rather than the person. For example, if we missed a deadline because someone didn’t perform well, we wouldn’t single the person out but rather ask what tasks or processes weren’t successful.
However, in rare cases when this approach doesn’t work, we escalate it to our manager who then handles the conflict. He makes suggestions around improvements we can make but never forces us to make them. In some cases, he just asks us questions that lead us to come up with solutions by ourselves.
How we think about meetings
Two 15-minute catch-ups daily
We control our day-to-day. As a remote team, we decided we needed a better way to stay in touch than just a daily standup meeting and some Slack messages. We needed more time to discuss projects, and the lack of regular informal sessions made us feel isolated from each other. We needed a way to get to know each other and ask questions outside of meetings with our client.
Thus, our most important process was born: two 15-minute catch-up meetings daily—one at 09h00 and another at 14h45.
These meetings are on everyone’s calendars, and they’re the main touch points for our teammates. There is no fixed agenda. Teammates can use these meetings to discuss development priorities, ask for help with tasks, initiate knowledge-sharing sessions, or chat about their weekend plans. The only constant is that one of the team members ends the morning session with a few jokes and then nominates another team member to do the same the next day. This ritual is a great icebreaker for new team members and contributes a lot to team morale.
Having our own meetings and rituals helped us to create and maintain our own team identity and culture.
Default to video on
For meetings, we opted for a video-first approach as far as reasonably possible. We felt much more connected if we could see each other’s faces to pick up on body language and non-verbal communication. Our team was formed in a time of extreme isolation during the COVID-19 pandemic, and our video-first approach was essential in building camaraderie and trust between our teammates.
We made every meeting open to everyone in the team, with attendance being optional as far as possible so that people in the meeting actually wanted to be there.
Our client appreciated the restructured meetings and voluntary attendance. Like us, any reduction in time spent in meetings is a bonus to them.
Batch meetings together
We try to maximise “flow” time by batching multiple meetings together. For instance, we would rather spend an entire morning or afternoon in meetings than space them throughout the day. We found that 30 minutes to one hour of free time did not allow us to work as effectively as working two to three-hour uninterrupted sessions.
People often ask us, “How do you justify adding two more meetings to everyone’s calendar every day? Isn’t the point to have fewer meetings?” These are valid and valuable questions. We discovered that many of our other recurring meetings, which were typically quite long, became unnecessary because we would discuss the topics of these meetings in our catch-ups. As a result, a number of our regular meetings became shorter and shorter until we could cancel and replace them with emails.
How we think about development and code review
Every one of our team members’ previous experience in code reviews was typical of many development teams. First, developers would get their tickets from the client or business analyst and start development. Then, other developers in the team would review it and deploy to a staging environment, at which point the QA team would come in and test whether the feature introduces any bugs in the system.
This process would result in things getting lost in translation. Developers might misunderstand the ticket or specification and develop a feature that doesn’t address the client’s needs. The QA team tests the feature after it’s developed and reviewed by the rest of the team. Only after this would the client or BA be able to say it’s not what they wanted.
Miscommunication like this results in friction between team members and between the team and the client. The feedback loop becomes drawn out, resulting in missed deadlines, frustration, and wasted time.
Involving the entire team in development and review
To solve this, we decided to involve the entire team in the development and code review process from the beginning.
We taught our QA and BA to work with Git. By building and running the project on their own machines, they can individually experience any issues developers might have. Typically, these issues aren’t visible enough or are too abstract for non-developers to understand completely, which makes them hard to discuss.
Our BA and QA are also the final approvers of pull requests, ensuring that anything that gets merged is properly tested and truly fulfils the client's requirements. In addition, we have a policy where the finalisation of open pull requests is the entire team’s top priority to ensure developers don’t waste time working with stale code or multiple branches.
Developers pull tasks themselves
Initially, developers were assigned tickets at the beginning of a sprint and committed to completing a specific number of tickets by the end of the sprint. Because tasks were assigned at the beginning of a sprint and were never reassigned during the sprint, some developers weren’t able to complete all their tasks. Combined with faster developers who finished their tasks early in the sprint and picked up new tickets not listed in the initial sprint target, we ended up with sprints where half of the promised tasks were completed and the other half of the completed work was out of the sprint's scope. This led our client to think they couldn’t trust our sprint commitments.
We decided to pivot from our “push tasks onto developer” methodology to a “developer pulls tasks themself” methodology. In Agile-speak, we switched from traditional Scrum to Kanban: Tasks aren’t assigned to developers but are pulled by developers. Our BA constantly maintains the priority of the tasks, and developers pick them up based on that order.
In addition to providing us with much-needed flexibility in quickly changing priorities when needed, we can deliver on what the client wants consistently. Developers also gain a wider variety of experience since they don’t get assigned tasks based on preference or expertise.
By focusing on what we were able to complete over two weeks rather than how close we were to what we’d committed to in that period, our delivery speed increased.
We can continuously calculate the average number of story points we complete in a day, and we use that figure to make estimates when we need to establish rough timelines.
How you can implement this in your team
We have been working fully remote as a self-managed team for over a year. We’ve experimented with different processes, reshuffled our meeting schedules multiple times, and sometimes even failed in our experiments. Throughout this entire process, we established that there are a number of key things that make our team successful.
- Multi-disciplinary and well-resourced teams adapt to this way of working much easier than a team consisting solely of developers or business analysts or <insert other job title here>. Each team member should be some sort of subject matter expert that addresses a specific need in the team. This prevents echo chambers and ensures that everyone brings something different to the table. Inter-disciplinary knowledge sharing is also exceptionally valuable.
- Teams should be responsible for their own day-to-day processes. This presents a great growth opportunity for teams to discover what works for them and what doesn’t and can result in the day-to-day being optimised towards making the entire team’s job as easy and efficient as possible.
- Have open lines of communication. By encouraging team members to voice their opinions and share information, you can ensure that knowledge is shared within the team, and trust is fostered between team members. No one should be afraid to reach out when asking for help or advice.
- Teams like this need a “culture champion”. This is the person who ensures that the team still gets exposed to your company or team culture, regardless of whether you are working from home or from an office. This person knows the unwritten rules of your company, and who to speak to to get things done. They are also usually the instigators of team socials. In our team, this quite naturally happened to be our most charismatic team member who also coincidentally had the longest tenure at the company.
- Build trust in your team. People want to know that you trust them to do the job they were hired for. You don’t need to constantly check up on them or track the amount of time they sit at their computers. Instead, set clear and achievable expectations and goals. Recognise personal and team achievements. Delegate tasks and allow team members to take responsibility for epics/features/milestones. Don’t play the blame game. And always work towards helping the team succeed, instead of focusing exclusively on personal gains.
- Encourage experimentation and regularly reflect on your experiments’ impact. Most of our most successful processes and decisions have come from the team deciding to try something out, regardless of whether it worked or not. We use fortnightly retrospective meetings for both our reflections and proposing new ideas. It’s OK if an experiment doesn’t work out - at least the team gained some experience and knowledge on why that was the case, and how it could have been improved.
This is what we found worked for us, and I sincerely hope that you, the reader, can also find value in the lessons we’ve learnt and the processes we’ve implemented.
Andreas Nel is a software engineer at Entelect Software, a software consultancy with a global footprint. He has experience in a number of web, backend, database and software infrastructure technologies. He spoke at both PostgresConf ZA 2019 and DevConf 2022, where he was rated as the best speaker at Johannesburg event. He is passionate about all things DevOps, and if he isn’t adding another idea to his list of (unfinished) side-projects, he can be found talking about different coffee brewing methods.