My team at CircleCI is made up of seven engineers, a product manager, a designer, and an engineering manager, and we are distributed all across the world: in the US from West Coast to East Coast, then to Serbia, Thailand, and finally Japan. Usually, we’re based in places like San Francisco, Chandler, Tempe, Boulder, Knoxville, Novi Sad, Bangkok, Fujisawa, and Akita. Two weeks ago, we were all meeting during an in-person team event in San Diego, and we asked ourselves a question: if we had a choice, would we choose to be a remote team distributed across distant time zones, or would we rather be at least closer together?
The answer was: we wouldn’t want to change a thing. Having to default to async communication suitable for cross-timezone collaboration means that everyone on the team has equal freedom and flexibility to work whenever and wherever they want. We value this freedom and flexibility, and the impact they have on our well-being is making us a stronger, more resilient team.
We only started forming as a team in January this year. Given our distribution, we’ve been very intentional and deliberate about how to succeed as a team from the start, and there were plenty of things we learned along the way.
Remote/async - tips & tricks
Here’s a curated list of practices we have developed over time to help us work together as a team across time zones. Many of them are heavily inspired by tactics we’d learned from previous teams we’d been on, and some we developed together based on the preferences of the folks who comprise our team.
One of the intentions we explicitly agreed upon when our team initially formed was overcommunicating, and it has proven to be extremely useful. Starting out as a widely-distributed team of mostly folks who had never met in person, we hoped overcommunication would help us at least avoid not communicating enough, and, at best, figure out what communication level we need.
In practice, overcommunication helps when hesitating in daily situations like:
- Is what I’m about to send via direct message to my team member relevant for them? Should I bother writing a message? Yes, overcommunicate!
- Is the timing of my message right? It’s Sunday evening in my colleague’s timezone! No worries, overcommunicate! They’ll decide on how and when to react (“do not disturb” and “silent” modes are our friends).
- My colleague may already know what I’m about to write to them about–should I stop? No, overcommunicate! Better to be safe than sorry.
- I need to step away from the keyboard to change my baby’s diaper, does my team care? Yes, overcommunicate if you can (and it’s okay to leave out details)!
- What I found in the diaper looked like Pantone 3995; should I let my team know? Well, maybe not that.
From the beginning, we were anxious about accidentally developing “subteams” split along time zones, and were looking for ways to prevent this. One such way we found useful was encouraging cross-timezone work, so-called “ping-pong” pairing.
“Ping-pong” pairing is similar in principle to traditional pair-programming, but asynchronous. Instead of navigating/commenting code the other person is writing in real-time, and switching driver/navigator roles often, we let our respective daily schedules dictate the rhythm. This still retains the usual pair-programming benefit of knowledge sharing, while actually allowing more than two people to participate in the process.
To facilitate “ping-ponging” we found it useful to:
- Limit our work in progress to 3 cards (number of engineers on the team, halved, rounded down). This encourages us to look for tickets already in progress before starting anything new.
- Post work-in-progress Pull Requests (PRs) as soon as possible. It should be natural that, unless someone is actively working on a given task at the moment, anyone should be able to read through the PR (and other relevant communication) and continue working on it.
- Hand off work in progress, either asynchronously on Slack, or in video calls when people’s working hours happen to overlap, especially at the day’s edges as one person’s day is ending and another’s is just getting started.
Slack is an important tool for our day-to-day team communication, as is the case with many other teams at CircleCI, too. We use it to communicate our availability, request help when needed, coordinate ad-hoc video calls, etc. We have one team channel, and it’s public for the whole company - members of other teams are welcome to join and participate when they need our assistance.
To help us navigate all the different conversations happening in Slack, we have developed a few useful practices. We:
- Use emoji to denote important messages. Especially when the whole team is overcommunicating on Slack, it may be difficult to scroll through all the messages on Slack at the start of one’s day, not to mention coming back from vacation. To alleviate this and make scanning our channel easier we started prefixing certain messages with emoji like:
- :mega: or :speaker: for PSAs
- :exclamation: for important warnings
- :information_source: for less important information
- :question: for… questions
- A custom “big red arrow pointing right” :status: emoji for taking breaks or signing off
- Surface important decisions made in threads. Some important decisions are made deep inside Slack threads (starting with the :thread: emoji); this is easy to miss, so we decided to always try to send important messages up to the main channel, too.
- Summarize video calls. We tend to “huddle” a lot, meaning jumping on ad-hoc video calls, to discuss issues at hand or hand off work when “ping-pong” pairing. This can sometimes make it difficult for people following the issue later on Slack, so we try to write quick summaries (starting with a cute custom :hug: emoji) of what was discussed and decided in a call after it’s finished. This helps ensure people understand what’s going on, even when they can’t participate synchronously.
Because of our spread across time zones, meetings aren’t an option for us during a normal week. But we enjoy synchronous time together and make use of it for smaller groups. Here are a few ways we’ve made it work:
- Embrace asynchronous stand-ups. There’s no time all of us can have a call, but daily updates are important. We were using Slack messages for that (emoji :standup:), now we’re experimenting with a tool called Range.
- Define weekdays. It may be difficult to know what “Wednesday” actually means, depending on who’s speaking (from which time zone). We’re defaulting to “Wednesday” meaning “North American Wednesday”, regardless of context. So I’ll say “let’s talk about this during our retrospective on Thursday” even though I work from Japan and that’s Friday for me already.
- Alternate time slots for retrospectives. Times for our retrospectives alternate every other week, to have both US-friendly and APAC-friendly times, and make sure everyone has a voice, is heard, and can contribute to improving our collaboration as a team.
- Record meetings by default and keep notes. For both planning and retrospectives, we make recordings (and notes for retrospectives) available for people who couldn’t attend.
- Schedule sync meetings if there are any “missing links.” While our engineers work from North America and Asia, the designer we work with is located in Europe. Every week, we have at least one synchronous call with him and any others who can attend, and create recordings and notes for others. Overcommunicate.
These are some of the things we’ve found that work well for our team; yours might be entirely different! What do you do to keep your team connected? We’d love to hear about it: tweet us @circleci with your tips.