"How can we move faster?" This is perhaps the number one question we hear from the CTOs we work with. Regardless of team size, industry or maturity, we consistently see teams struggle to effectively scale. In a few extreme scenarios we have also heard "I am spending more on software, yet, somehow, we're actually seeing less software get released. How the hell is this happening?"
Here are some symptoms of a team that is struggling with growth:
- Problems organizing work - Entire teams are stuck waiting on product requirements or on other teams
- Too many hurdles make the slightest of changes to production take a very. Long. Time.
- Paralysis by analysis - Teams stuck debating on how to implement something
There are ways to reduce the negative impact of growing your team. In this post, we’re going to discuss some of those strategies we’ve seen work. We’ll start with the less technical topics and end with the more technical ones.
First up, the people!
Talent
This will sound cliche, but it all starts with hiring. Hopefully you’re reading this because you want to know how to scale your team before it’s too late.
Start with strong technical leadership. Hire this talent first. By “technical leadership” we do not mean “managers.” We mean player/coach talent who do the work while building out a team, then move to full time leadership.
When picking your technical leads, it's best to prioritize communication skill and curiosity over technical ability. You want a leader who is technically sound, but more importantly, you want a leader who asks good questions, exposes shortcomings and most importantly knows when they are in unfamiliar territory.
After you hire your technical leaders, you want to make sure you have a good balance between leaders and individual contributors. Don’t just hire all senior engineers, or you’ll have a situation where you have stalemates on technical decisions all the time. Ideally, you have a balance of people who will want to lead the charge, and people who are more junior and eager to learn. In all of these roles, curiosity is a key trait to look for.
Finally, make sure you have a large enough product and/or business team to backup your technical team to help drive work forward. A technical team without enough product owners and/or designers to back them is as good as not having a software team.
Communication
Tribal Knowledge is a often-used term for the stuff that your team knows but isn’t codified yet. When you’re starting up, there’s no time or need to write those things down or automate them. It’ll just slow you down. The fact that this knowledge is just known on the team makes it a well oiled machine.
But as you grow and new people come onto your software team, they only find out about these things by happenstance or even worse when an issue comes up and they’re not sure how to fix it. So it’s important to make sure your technical leads set goals for their teams to codify their knowledge. Reward transparency and information sharing. Simply dumping all the knowledge into a document or wiki is not enough, this needs to be thoughtful and strategic.
Here are some other ideas to consider to get ahead of this as you think about scaling your teams:
- Make sure that issues are documented alongside your features so they can be folded into work streams
- Set aside some time periodically to prioritize automation of tasks that require tribal knowledge.
- Make sure that code comments which document the “Why? Rather than the How?” are prioritized and vetted during code review processes. Keeping this documentation as close as possible to the code itself is much better than distributing it in different places like a document or wiki.
- Have a Runbook (or possibly Runbooks) from the very beginning, no matter how small the team. These are documents that everyone knows they go to for keeping a system running smoothly. They should be treated as sacred and updated with every release.
The Technical Things
There’s a lot to cover here, so bear with me...
Make significant investments in DevOps & Testing
It’s critical to make sure that your developers can easily get started running a system locally. As your team grows and new people have to create this setup (or, existing people get new computers!) this can slow you down immensely.
So how can you get ahead of it? Prioritize automation. Whether it be through specific talent like DevOps or Site Reliability Engineers or Release Managers, or just making it one developer’s priority to script things - make sure that a new developer can get started in a few hours at the very most.
Even in the earliest phases of your project, make sure you also have a fully automated Continuous Integration / Continuous Delivery (CI/CD) pipeline. Regardless of the solution, it should be as easy as pushing code to a branch or clicking a button to deploy to production. Whatever you do, don’t give into the temptation to manually push code out! It will come back to haunt you before you even get the software out to users.
In concert with CI/CD pipelines, invest in Infrastructure as Code (IaC). We recommend Terraform. These tools let you describe your cloud environment and create it with one command. Using these types of tools not reduces your risk of environments being different, and also gives you the ability to spin up new environments very easily.
Code Organization & Decoupling
One of the most significant (and obvious) pain points on large software teams is when multiple people are doing work on the same piece of code at the same time. The team ends up spending more time fixing source control conflicts and coordinating than actually producing value. There’s no perfect way to organize code, but if you give it some effort up front and adjust as you go, it’s a pretty easy discipline to get into, especially if it's part of your code review process.
- Make sure from the get go that you’re not putting all your code in a few modules or files. Once you hit a certain point, separate files will become unsustainable. You will smell the code rot from a mile away.
- Consider contract-driven services (lowercase s) within the same application. Many of the benefits of a Microservice architecture are derived from the concept of Domain Driven Design, specifically the idea of a bounded context. If you can come up with the right bounded contexts for services within your application, you can then work to define contracts for those contexts using simple code documentation or even going so far as to use things like OpenAPI. By defining the contract of a bounded context, you can then split work out across teams and make sure that they work with each other’s code through those contracts.
- Once you hit a certain point, separate files will become unsustainable. Once you start to sense this oncoming disaster, it probably makes sense to create a separate API or application for some portion of your system. At that point in time, if you’ve created the right bounded context and have a well defined contract, this exercise will be a lot easier, and there will likely be a team who is already well versed in that particular service that needs to be split out.
Speaking of services...
What about Microservices?
We’ve heard the buzzword “Microservices” thrown around as a panacea to fix many problems in scaling and organizing software. The most important thing to remember is: Don’t conflate a well-organized application with Microservices. A well organized application with separate domains is always a good idea. Microservices may or may not be a good idea.
There are many situations where a microservice architecture will help, but in order to “Do Microservices Right” you need all kinds of foundational architecture in place. Start with simpler options like those described above in the “Code Organization” section. You’re effectively forcing your teams to work as though they were using a Microservice but without all the headaches of separate deployments, dealing with cross service transactions, etc. You’re getting yourself more than 50% of the way there, but keeping things simpler, and more importantly, letting your teams scale-out more.
Hopefully, this post has given you plenty to think about as you’re growing your team. We feel strongly that an organization that can scale is really driven by people, culture and communication, more so than technology. As we always say at Rocket - technology is an enabler of great experiences - it’s a tool to use to get to a goal, not the goal itself.
If you want to learn more, check out the extended ebook version.
In the meantime, good luck growing your team!
Rocket Engineers Adam Fraser and Jon Principe, as well as Rocket Founder Jesse Streb, contributed to this post.