- Create clarity for everyone such that they know what they need to do and how it fits into the bigger picture.
- Communicate openly. Give team members a stage to be publicly competent.
- Pick up the grunt work that others might not find enjoyable.
- Allocate time for support work, e.g., reviewing user feedback and error reports.
Usually, the reason a project is difficult isn’t that you’re pushing the boundaries of technology, it’s that you’re dealing with ambiguity: unclear direction; messy, complicated humans; or legacy systems with behavior you can’t predict.
As a tech lead, the folks working on the project may not be reporting to you, but you’re responsible for the result. You’re thinking about the whole problem, including parts of it that aren’t really anyone’s job.
The Start of a Project
If You’re Feeling Overwhelmed…
It takes time and energy to build the mental maps that let you navigate it all. The difficulty is the point. Ambiguity is the nature of the work – if it wasn’t messy and difficult, they wouldn’t need you. You got to the lead role with credibility and social capital – ten mistakes will not destroy you.
Create a document to act as an external part of your brain for the project’s duration. Fill it with uncertainties, rumors, leads to follow, reminders, to-dos, etc.
Talk to your project sponsor. Write down what you think they’re hoping to achieve. Write down what they’re telling you and double-check that you got it right. Clear up any confusion about what you’re role will be and who you should bring project updates to.
Your junior engineers are looking for safety and stability. Find one person who you can be open and unsure with, e.g., your manager, a mentor, or staff engineer peers. Be that person for others too.
Don’t waste the brief period where it’s cognitively cheap to not know. Take any step that helps you exert control over the problem: talk to someone; draw a picture.
Use your strengths. If more comfortable with code, jump in. If you tend to go first to relationships, talk to people. If you’re a reader, go to the docs. Start convincing your brain that this is just another project.
Building Context
Out of all the possible business goals, the technical investments, and the pending tasks, why is this the one that’s happening? If the project you’ve been asked to lead won’t achieve the goal, then reject the premise of the project. Better to find out early.
It’s not easy to understand what your users actually want – as opposed to what they’re telling you. Ask a user to let you shadow them using the software you’re replacing. Ask internal users to describe the API they wish they had. If you have UX researchers studying the customer experience, read their work, talk to them, observe some user interviews.
Make sure that your sponsor and any other leads on the project agree on the success metrics. Will it mean more revenue from users, fewer outages, a process that takes less time? Treat your own ideas with the most skepticism and get real, measurable goals in place quickly.
Understand the constraints, e.g., deadlines that can’t be moved, teams that you depend on that might be too busy to help, etc. Set your own expectations and other people’s too.
Be clear about your areas of uncertainty. What could prevent you from meeting the deadline? What don’t you know, and what approaches can you take to make those less ambiguous? Make frequent iterative changes so you have a better chance of getting user feedback and course-correcting.
Respect what came before. Where did the idea for the project come from? Have teams tried and failed to solve the problem – how to engage their enthusiasm again? Are there existing users with odd use cases that will still need support?
Sometimes what came before was attempted by previous team members who have since left the company. Steel-manning their approach should be more useful. For example, it’s not as if my docs are the ones that will be easily discoverable in the future – where are the original docs and how could they be more visible?
Know key people that you should talk regularly with. On a bigger project with many teams, you’ll need a contact person on each team. Understand who the leaders are and what role they’re expected to play lest you waste time in power struggles.
Giving Your Project Structure
Define leadership responsibilities, e.g., understanding customer needs and providing initial requirements, providing KPIs for product success, setting timelines, setting scope and milestones, managing team members' performance and growth, mentoring and coaching on technical topics, designing high-level architecture, communicating status to stakeholders, devising A/B experiments, making final decisions on technical approach, making final decision on user-visible behavior.
Having a process for making decisions helps prevent two common failure modes: never making a decision because it’s not clear who the decider is, and re-litigating every decision over and over.
As a project lead, you’re implicitly filling any roles that don’t already have someone in them. If no one’s tracking user requirements, that’s you. If nobody is project managing, that’s you as well.
Recruit people for unfulfilled roles that you don’t want to do or don’t have time to do. Look for people with complementary skills, e.g., if you’re a big picture person, look for someone who loves getting into the details.
Other than having worked with folks in the past, how do I take stock of the skills that are available in the team, and find people with the missing skills?
Agree on scope. Deliver incremental value, and be prepared for each incremental change to potentially change the user requirements for the next one. Changing what your users can do helps them realize what else they want to do.
Make the increments small enough that there’s always a reachable milestone in sight. Place a date on that milestone so that folks act with a sense of urgency.
It seems that by definition, deadlines should not be aspirational. Need a better visual on how realistic a given date is. I’d like to have timely delivery without inducing stress for the sake of a date.
If the project is big enough, split the work into work-streams, chunks of functionality that can be created in parallel, perhaps with different sub-teams, each with its own set of milestones. This lets you talk about any one of them independently from the others.
Time estimates are hard. Update your schedules as you gain experience with the problem. Practice estimating even when it doesn’t matter and see if more of your estimates are right over time. When estimating, figure out the availability of teams that you depend on too.
Agree on logistics. How often are meetings, demos, retrospectives, etc.? How will you encourage informal communication? How and when will you share status with the project sponsor? Where will the documentation home be? What will the development process be, e.g., standards for code review?
While all of the important information is written down already, having a kickoff meeting helps start a project with momentum. Be explicit about what you want people to do. If you’re ambiguous, then you’re making more work for everyone else as they try to figure out how much the thing you’ve asked for matters.
Driving the Project
Exploring
Understand the project’s goals and evaluate the approaches. If it’s difficult to articulate the goals, or the goals are a description of your implementation, then spend more time exploring.
Different teams have different mental models of the project, e.g., they think your project will also achieve some other goal they care about. Be able to concisely and accurately explain what different teams want.
Sum up the project and reduce it to its most important aspects. Build up a clear description of what you’re not doing. On related projects, how do they overlap? Is there work that seems familiar but isn’t actually related? Is there work that seems unrelated but has unexpected connections?
Don’t cling tightly to your original ideas, resisting all information that contradicts that worldview. Existing work might not match your vision, but be receptive to the idea that it might be workable, and one less thing to maintain going forward. Understand whether similar projects have succeeded or failed, and where they struggled.
This might take the form of defining the goal in terms of the implementation. When that’s the case, dropping the implementation might feel as if you’re declaring defeat.
Clarifying
Unlike folks chipping in, you’re incentivized to grok the tricky concepts. Take the time to reduce the complexity for them lest they optimize for the wrong outcome. How can you hook the concepts onto their existing knowledge?
Take time to understand what words are meaningful to the people you intend to communicate with. Use their words when you can, or deliberately describe what you mean by the terms you’re using.
Visual representations help reduce complexity. If something’s changing, use “before” and “after” pictures. If showing progress towards a goal, can you use a graph?
Designing
No objections when you talk about ideas for what comes next could be a result of your colleagues not having internalized the plan. Write things down to ensure everyone is aligned. Include the important aspects of the plan so that others can spot hazards in the path. Agree on whether your assumptions on other teams or systems are correct. A written design is very cheap iteration.
A Request for Comments (RFC) document is helpful at this stage. Most companies have an RFC template. Heroes need not improvise; a good template helps us avoid common mistakes and make the right decisions intentionally. An RFC should:
- Anchor in space and time. If read in 2 years, can the reader decide its relevance from the header? What’s the status, e.g., early idea, implemented, on hold, etc.
- Show what problem you’re trying to solve. Provide enough information for readers to decide if they think you’re solving the right problem. The specific implementation should serve the goal; it should not be the goal.
- Lay out how you intend to achieve the goal. Provide enough information for readers to evaluate whether the solution will work, e.g., APIs, pseudo-code, architectural diagrams. Wrong or controversial is better than vague.
- Consider security, privacy, and compliance. Be explicit if you think no considerations are needed.
- Describe alternatives and prior art. Why wouldn’t they work? If some other team has a related solution, send the RFC to them and collect their input.
Watch out for these technical pitfalls:
- Assuming it’s a brand new problem. It’s rarely the case. Learn from other people; consider reusing existing solutions.
- If another domain seems easy, it’s because you’ve not internalized that it’s as rich and nuanced and complex as your own.
- Will your solution still work in 3 years? Will it become a bottleneck for other teams?
- “We might need it later” as a justification. Explain why designing for a few orders of magnitude more than current usage is a good investment right now.
- Any part of the solution that involves humans changing their workflows will be difficult.
- Figuring out the difficult part later might turn out infeasible or push the complexity to someone else (e.g., API breakages instead of backward compatibility).
- Solving the small problem by making the big problem less tractable. Either engage with the difficult problem directly, or call out the tradeoff in the design.
- Thinking it’s not a rewrite, but in practice it is, e.g., re-architecting for the cloud. It’s going to take much longer.
- Make processes as boring and self-documenting as possible. If you struggle at 3pm, you won’t understand it at 3am.
- Bike-shedding. Don’t spend time deliberating trivial and reversible decisions.
Coding
Most project leads review a lot of code, but don’t write much themselves. Writing code is rarely the highest leverage thing you can spend your time on.
Your time will be the least predictable. Don’t work on code that is time-sensitive or on the critical path. Aim for your code to empower your team, not to take over from them.
Find opportunities for other people to grow, especially on the important changes. Provide an opinion or two. Pair-program for key parts of the change and leave the colleague to complete the work.
If there are implementation constraints that you’d rather not compromise on, specify them in the work item. The constraints should be the goal, and the implementation should be in service of that goal. For example, “The search module should be extensible to support filtering as well. An implementation could be…”. In this case, I provide my opinions why still giving the implementor room to be creative about it. The implementation suggestion serves as a clarifying exposition and not a prescription.
Let the rest of the team think of you as a resource to learn from, not someone who criticizes every decision and makes them feel inadequate. Let someone set a pattern that’s good enough without overruling them. Don’t be the one doing all the code reviews lest you be a single point of failure without the team learning as much.
Whatever you do sets expectations for the team. Meet/exceed testing standards, add useful comments, and be careful about taking shortcuts.
Had a successful work project with regard to shipping well tested code. By figuring out how to structure my tests, other devs followed the patterns I established. Sometimes it’s not that folks don’t want to do something like testing, but more that the testing approach itself is ambiguous, and having a trodden path makes it easier to add the next set of tests.
Communicating
Make it easy for team members to reach out and ask questions, and disagree without it getting tense.
Having a “water-cooler” long-lived chat seems to help. Takes the pressure out of needing to have polished questions. Some folks are also more comfortable asking questions in smaller group settings. That said, smaller group chats can lead to information silos where techniques are unnecessarily re-derived from first principles :-/
Make it easy for sponsors and customers to find out the status. Too much detail can obscure the message. Explain the status in terms of what the audience will want to know, e.g., what can users do right now, and not that you stood up three micro-services. Lead with the headlines. Follow facts with “that means…” or “so that we can…” Avoid being a watermelon project; if the project is stuck, don’t hide it: ask for help.
Navigating
Assume that something is going to go wrong – you just don’t know yet what it’ll be. You’re responsible for re-routing, escalating to someone who can help, or breaking the news that the goal is now unreachable. Communicate well; don’t create panic or let rumors start. Your sponsor wants your project to succeed; telling them you need help gives them a chance to do their jobs.
References
- The Staff Engineer's Path: A Guide for Individual Contributors Navigating Growth and Change. Chapter 4: Leading Big Projects. Tanya Reilly. 2022. ISBN: 9781098118730 .
This is a muscle that I don’t yet have. The ratio of PMs to SWEs isn’t that high, and thus I’ll need to don the PM hat in some projects. That said, the PM world is as nuanced and rich as the SWE world. How do I not end up with two full-time jobs?