How to tech lead a software project

The software engineering project DRI checklist

Angela Zhang
13 min readOct 30, 2019
My team at Plaid: we wear tracksuits and lead projects.

Most projects should have a Directly Responsible Individual (DRI). This role might have different names depending on the company: project lead, tech lead, benevolent dictator… (ok, I might have made up the last one). At the end of the day, it’s the project DRI’s responsibility to make sure the project is successful.

This is worth repeating and internalizing because the buck stops with the DRI. If the project fails because it wasn’t staffed with the right people, or the elegant technical solution you built didn’t solve the actual product problem your customers have, or any of the other myriad reasons why a project might fail, as the DRI, you are ultimately accountable for identifying these failure cases early and mitigating them.

If this all sounds like a lot to think about, it’s because DRI-ing a project is really hard. And it only gets harder when your projects get larger in scope and have more uncertainty.

To make this hard job slightly easier, the rest of this post talks about the “how” of being a successful project DRI. On a high level, the responsibilities of the project DRI are:

  • Decision making: Having a good consultative decision-making framework, being willing to move forward with a decision even when you don’t have all the information.
  • Intra-team project communication (if your project includes multiple people): Prioritizing and splitting up tasks amongst the team, making sure all the necessary work gets done (including the less glamorous work), setting up a project cadence so everyone can collaborate effectively and surface potential problems, setting up an effective feedback sharing mechanism, running project kick-offs and retrospectives.
  • Stakeholder communication: Knowing who the stakeholders are, and proactively communicating to them at the right level of detail.
  • Higher-level thinking: Asking the hard questions, defining the goals of the project and getting buy-in for these goals, thinking 3 steps ahead to anticipate the next roadblock.
  • Technical execution: Writing a spec to get feedback and align work, scoping and sequencing tasks, ensuring the project meets the technical quality bar (varies depending on the maturity of the product), tracking clean up work and future feature requests.

Next, we’ll dive into how to do these things at different stages of the project in a lot more detail. This post is most relevant to projects spanning several engineers and months, but the principles here are relevant to both an engineer doing small solo projects, as well as someone who’s tech leading a team or system long term.

At all stages of the project

Photo by Andrea Leopardi on Unsplash

Think 3 steps ahead.

Every week, think critically about the project and ask yourself: Am I doing everything I can to make sure this project is successful? Anticipate what the next roadblock is going to be and what the potential risks are.

  • On the technical side, ask yourself and the team: What will be hard about this? Which part makes you nervous? What’s risky? What is falling through the cracks? What’s harder than expected? What did you learn last week that changes the assumptions you made? Then work on the hardest and riskiest part first, instead of taking the “we’ll figure this out later” approach and then be met with an impossible roadblock after doing months of “easy” work.
  • On the nontechnical side, ask yourself and the team: Is this a sensitive change that would require time for the GTM teams to communicate with customers? Do we need to line up external vendors ahead of time (because onboarding a vendor always takes longer than you expect)? Do you need buy-ins for any other function/team? When do you need to loop in Person X and Y?

Use the consultative decision-making model.

That means: solicit feedback from others, but ultimately you make the call and you are accountable for it. Consultative decision making often means someone might be unhappy about this decision. In-person meetings can be an effective way to try and resolve these disagreements. And as the DRI, you should absolutely make sure everyone has a chance to make suggestions / raise any concerns. But ultimately it’s your job to make a decision, even if others still disagree. I want to specifically call out that the goal isn’t to get everyone to a consensus. Consensus driven decision-making often leads to the option everyone “hates the least”, instead of a “risky but ultimately worth it” decision. A classic example here is Facebook would never be able to build a newsfeed if all the product execs need to first agree it is the right thing to do.

You have to be willing to make a “good enough” decision quickly and move forward, even in cases where you don’t have perfect information to make the “best” decision. Ask yourself: “is this decision reversible?” If the answer is yes, moving forward quickly with any decision is better than being blocked and waiting with no-decision. If the decision isn’t reversible, acknowledge all the tradeoffs and potential risks, then pick the one that you think is right when you are 90% sure (because getting to 100% is either unattainable or far too slow).

On the flip side, know that you don’t have to do this alone. Ask your project team members for their input. Ask another engineer you respect. As your manager. Walk them through the options and tradeoffs, and get their input before making your decision.

Take a breadth-first-search approach towards finding potential solutions.

For every problem, try to come up with a set of options and tradeoffs. Some prompts you might think through:

  • What’s the most lightweight way to solve this problem? E.g. if you think you need another team to support the change you are trying to make, is there a creative way you can somehow implement the change entirely within your own systems?
  • What’s the most durable way to solve this problem? If you run across a milestone where your original “ship the MVP” approach is actually much more complicated and time-intensive than you expected, should you spend a bit longer to just do it the most robust way?
  • What’s the safest way to solve this problem? Do you detect the most failure modes through diff logging? Integration tests? Manual smoke testing?

Remember to cast a wide net in terms of potential options. Could you borrow an engineer from another team for a sprint to overcome an issue in their system? Should you have an engineer roll off the project early because there are too many cooks during the rollout phase? You can advocate for more than just technical solutions.

Before the coding starts

Photo by Braden Collum on Unsplash

Define the goals and non-goals of the project.

This could come in the form of key results or some combination of success metrics and defensive metrics.

Proactively consult your stakeholders.

These stakeholders can be GTM teams, downstream engineering teams that are waiting for your project to ship, your manager, etc. Talk to these stakeholders as early as possible, give them context, and invite them to the conversations (in person or async) where decisions are getting made.

Make sure all the stakeholders and project team members are on board with your project goals and non-goals. For some projects, the impact might be less clear and that might mean you need to advocate for why it’s important to do it in the first place.

Write a spec.

For substantial projects, write a spec. Once upon a time, I wrote about the importance of a spec, the spec process, and what should go into a spec in a blog post so I won’t repeat it here.

Scope the work.

I’ve also written a whole post about scoping in the past so I’m just going to shamelessly plug that post instead.

Establish an agreed-upon project cadence.

Some projects are inherently less concrete and harder to plan ahead of time. For these projects, consider starting by just trying a lot of things out and having daily syncs to trade notes. On the other hand, for projects that have a clear path, weekly syncs are probably fine. Ask your team questions like:

  • How does everyone like to work together?
  • How often should we meet and talk about the project?
  • How much should we plan upfront vs write hacky code and iterate?
  • How should we divide up work amongst the team?
  • How are we tracking the various tasks in the project (Jira, Asana, Notion, spreadsheet, Google doc, etc)?

During the project

Photo by Jeremy Lapak on Unsplash

Proactively update stakeholders.

You’ve already consulted your stakeholders before kicking off the project. Inevitably, as you work on this, surprises will arise and you’ll make decisions based on these surprises. Agree on a cadence of project status updates with your stakeholders, and proactively surface to them any surprises, issues, and key decisions, instead of waiting for them to ask for project status. Career pro-tip: your manager is almost certainly one of these key stakeholders.

I’ve seen people successfully update the project stakeholders by setting up regular (every 2–4 weeks) meetings. I’ve also seen people do this via regular email updates which is more lightweight. The most important things you need to communicate with these stakeholders are:

  • What’s the ETA of this project / are we still on track to hit it?
  • What are the significant decisions you’ve made since the project was originally kicked off?
  • How do these decisions impact the stakeholders?

(Re)prioritize constantly.

Constantly prioritize work and reprioritize based on what you’ve learned. Here are a few prioritization frameworks that’s worked well for people:

  • One of my coworkers Nathan uses the “important-urgent-blocked” framework. For each task, consider: (1) how important is this task? (2) how urgent is this task? (3) how much does this task block other tasks? Then do tasks that rank highly on these 3 dimensions first.
  • Another coworker Max’s prioritization framework is “do the riskiness / unknown first”. Basically, if there are 10 tasks to do before anything can be shipped, do the scariest one first, instead of letting fear convince you to procrastinate by doing the less risky ones. That way, if you get blocked on the risky unknown task, you can always fall back to working on the other stuff in parallel.
  • For some projects, I’ve also had a good experience with the “ship something ASAP” framework. In other words, do tasks that lead to the project delivering value as soon as possible. This usually means breaking the projects down into the smallest shippable chunks (e.g. first swap out a backend without any refactoring/feature improvements), so you can start seeing impact for a 3 month project after the first month, instead of seeing no impact for 3 months, then realizing all the impact only after the full project concludes.

Regular syncs with the team.

Have regular (weekly) project team syncs for people to (1) raise potential issues, (2) make and align on design decisions, (3) have higher-level discussions that are larger than what can be covered in a PR discussion (e.g. should we change the goal of this project based on what we learned since starting on the project?). These syncs are also a good way to talk about whether people are splitting up work effectively or stepping on each other’s toes. Each sync should have an agenda beforehand that everyone can add to, and end with action items. As the DRI, you should take notes at these meetings.

You might also want to consider having biweekly or monthly 1:1s with project team members. These 1:1s give you an opportunity to give and receive feedback, as well as understand each other and the project better.

If your project doesn’t already have a Slack channel, you should make one ASAP. Even if it’s a small project, make a channel instead of relying on DMs.

Project/task management.

Every team does them in different ways: Jira, Asana, Google Doc, Spreadsheet, Dropbox Paper, Quip, Notion, name-your-trendy-task-management-app. It doesn’t matter what tools you use internally within the project team, as long as everyone is on board with using that tool. Make sure whatever you are using to track tasks lines up with project milestones so you can spot a project that’s falling behind as soon as possible. Try to figure out what the other engineers on the project are good at and what they want to learn, and suggest tasks based on that. Keep in mind that team members aren’t interchangeable: find the work that each team member would excel in and be pushed to grow, without setting someone up to fail because their Task Relevant Maturity is just too low for this task. If you aren’t sure, you can always sanity check with that engineer’s manager to make sure their tasks align with their interests and goals.

Don’t forget the less glamorous work.

It’s easy to get excited about the high visibility, glamorous work that makes the engine run. But as the DRI, it’s your job to also keep track of the hygiene/housecleaning technical stuff: writing tests, writing documentation, budgeting time for hardening, cleaning up your feature flags and old debug logs, setting up good monitoring and alerting, removing the dead code that your project replaced, fixing that “TODO: hackily hack hack”… You get the idea. The work that you desperately want to skip so you can move onto the next shiny exciting project, but the work that you know a future engineer is going to resent you for not doing. Someone’s gotta do it. Making sure those tasks get done can be as easy as adding tasks to your task tracking tool of choice, then asking your project teammates to self-select tasks.

There’s less glamorous non-technical work too, e.g. documenting important decisions, communicating with stakeholders in different teams and functions, taking notes at meetings and distributing notes, talking to external vendors, etc. If a teammate on your project is excited to proactively take these on, great. But if something just needs to be done and no one else is planning to do it, it’s your job to make sure it gets done.

You don’t have to do everything yourself.

Being a DRI doesn’t mean you do all of the work (and it definitely doesn’t mean you do all of the most interesting technical work). The DRI doesn’t have to make every technical decision. The DRI doesn’t have to understand every line of code. The DRI doesn’t even need to be the most technically experienced person on the team. But being a DRI does mean you need to make sure everything gets done. You should know when to step back and create an opportunity for others on the project to lead, though you are still ultimately accountable for the success of their work.

After the project completes

Photo by RUN 4 FFWPU from Pexels

Run a project retrospective.

Your project probably didn’t go perfectly. Learn as much as you can and share with others. Here’s the Plaid project retrospective template that also includes some instructions on the process around it.

Give both positive and constructive feedback to everyone on the team.

If there are multiple other people on the project team, encourage them to give each other feedback as well. Ideally, feedback giving is something you should be doing throughout the project, but if you didn’t do it then, definitely do it at the end.

Tell your stakeholders what you shipped.

For an internal facing project, this usually means telling users of your project why they should use your new shiny thing and how to use it. For an external project, this likely means working with GTM functions to market and ship it to users.

Do the follow up work.

I’m going to repeat this from before: don’t forget the less glamorous work. Make sure there’s a process in place for getting stuff in the backlog prioritized. Some teams set priorities on all tasks and use that. Some teams do periodic backlog-pruning. The failure case here is you think of all these things and stick them in the backlog, then they get mixed in with a bunch of P3 and WONTDO stuff, never to be found again. What’s your plan to make sure the follow up technical tasks get done? If there’s going to be a V2 of your project, keep track of what work should be part of V2 while things are still fresh on your mind. You might also want to clean up some of the technical shortcuts you’ve put in once the project has proven to generate value.

Just because the project is officially shipped doesn’t mean you are done. Ongoing maintenance and surprise feature requests take time. Your feature will probably break at some point in creative ways you didn’t think possible. As the DRI, it’s your job to make sure these unanticipated follow-up work gets done.

Finally…

Every successful project DRI has their own style and what’s worked for them and not worked for them. The main thing they all share in common is this strong sense of ownership and responsibility for the success of the project. Everything in this post are tools that we’ve found to increase the DRI’s chance of success. Ultimately, as long as you hold yourself accountable for the project outcome, you should pick and choose whatever tools work best for you (and drop a comment to let me know what works well for you).

Huge thank you to Max Johnson, Kent Rakip, Nathan Tindall, Brian Jacokes, and Joy Zheng, whose invaluable input and feedback to early versions of this doc taught me a lot.

Want to work with these amazing engineers? We are hiring!

If you like this post, follow me on Twitter for more posts on engineering, processes, and backend systems.

--

--