On Programming "Flow" in a Remote-Work World

By Peter Cottle

April 28, 2021

This blog usually focuses on how engineers build @Instagram, but today we have a story about tools we build to help engineers build @Instagram.

The Problem

COVID-19 and the shift to remote work has affected us all, but one of the less-talked about side effects is on that of engineering productivity. One of the most frustrating moments for engineers is being interrupted in the middle of a task after building up a large amount of mental context; this is perfectly illustrated by Jason Heeris’s comic below (used with permission):

Jason Heeris comic that demonstrates a programmer losing a lot of context when interrupted at their desk

When we worked together in an office, it was easy for coworkers to avoid this common distraction. If an engineer looked like they were in deep concentration (perhaps with headphones on and dozens of tabs open on their monitor), colleagues would abide by the common courtesy of waiting until their next break to ask them a question. It was even fine to politely decline a conversation until later, as illustrated in the popular movie The Social Network.

This standard of behavior allows for non-urgent communication to be delayed based on someone’s focus state until the next reasonable break. This provides an improved balance between communication latency and engineering productivity — a tradeoff that the industry should consider more deeply.

Now with remote work though, those in-person signals are entirely lost. Instead, we blindly send requests through apps like Slack that push notify coworkers on the other end.

Consequently, the number of interruptions an engineer experiences has gone up — a lot. After analyzing internal data, we discovered that a large portion of engineers have less than an hour a day to work in their IDEs uninterrupted before a message (or meeting, or another tool) pulls them out of concentration. Even just reading the preview of a desktop notification can be enough to alter your immediate train of thought and affect productivity in the long-run.

Coding is what we want to do -- it's what we studied, what we were hired for, and what makes us feel productive and accomplished -- but it's difficult to get distraction-free time to actually do it. Industry research from Microsoft additionally shows that interruptions in our day negatively influence how we rate those work days emotionally.

With all of this in mind, a few engineers got excited to prototype solutions as a side project.

The Solution

The Facebook engineering org started with an initial product called “Focus Blocks” to help address this issue. Focus Blocks are time ranges that an engineer would schedule during their day to focus on work. During these times, Do Not Disturb (DND) is activated so all incoming messages are sent silently to avoid interruption. The sender of these messages would also be informed to expect a delayed response, unless they used a specific override keyword like so:

An example message sent to someone in a Focus Block where the message does not push notify.

While this was a first great iteration, it also had some downsides. Engineers had to pre-schedule their focus blocks and manually extend the block if a task took longer than expected. Lastly these blocks did not automatically disable if the engineer stopped to take a break or answer messages; this resulted in a confusing experience for the sender in those conversations.

We knew there was a better way to build on top of this solid foundation and improve focus blocks. Instead of manually scheduling them, what if the developer environment (IDE) itself could detect that you were in deep focus? Then the tooling could automatically reflect your own mental state with none of the scheduling overhead.

Consequently, an idea called “auto-focus” was born to pursue this goal. By using a combination of real-time data from VS Code (our most popular IDE) and other tools, we built an algorithm to detect when an engineer has entered deep focus and enable Do Not Disturb mode.

First our algorithm needed data gathering which works as follows:

  • Any action taken by an engineer in VS Code is added to a private log. These actions include file opens, symbol highlighting, scrolling, terminal opens, or source control commands — general things you are doing when reading and writing code.
  • The times when an engineer sends a message are also privately logged. This data source prevents us from enabling DND if the engineer is actively having a conversation (while also coding).
  • Lastly, a variety of other tools that assist in software engineering (documentation, code search, etc) are also recorded to provide a secondary auxiliary signal.

All of this data is collected privately and used for Auto-Focus analysis only. Once we have this real-time series of data, we get something like this:

Table of real-time activity data across various developer tools with precise timestamps and categorizations.

The next step was to determine when an engineer was in focus state from this time series of data. This algorithm unfortunately wasn’t very straightforward and we iterated on a number of approaches. First we used the simple volume of actions performed within the IDE within the last 15 minutes; while this detected people entering auto focus, it also produced a huge variance between engineers who issued a ton of keyboard events (sometimes meaninglessly) and those who used actions more sparingly. In our second approach, we normalized the volumes of these events. However, this failed to account for secondary signals like code search and documentation reading — meaning that sometimes we pulled engineers out of focus when they were still actively working on a task.

We landed on this final iteration of logic that provided a reasonable tradeoff between recall and precision:

  • The last ~20 minutes of time are divided into 1-minute chunks
  • Any minute where an IDE action has happened is labeled as a “productive” minute. Any chat message sent during that minute removes that label.
  • If there are 12 or more minutes with a productive label (in the last 20 minutes), the engineer has entered “focus” mode. This means DND is enabled, and coworkers are informed that any incoming messages will be read later:
An example message sent to someone in Auto-Focus, where the message does not push notify. Additionally it shows that the recipients last action in the IDE was 41 seconds ago
  • Focus mode will continue as long as either soft tools (like code search) or IDE actions are taken. Once all activity has subsided, the engineer is removed from focus mode and a private summary of their session is sent to them, with small encouragement messages that acknowledge their productivity:
An example message sent to someone after they finish focusing, encouraging them because it is their third day in a row being focused.

This approach achieved a better trade-off between signal and noise; it turns out that how long you’ve been coding (rather than how much you’ve done so far) is the best proxy for your mental state.

Reception

While Focus Blocks already got a lot of positive reception, Auto Focus blocks provided incremental value that was appreciated by the ~2,000 engineers who are testing this prototype. Here’s an example quote from a round of feedback:

Thank you for building the Balance Bot Auto-focus functionality! It has been invaluable in helping me develop good working habits and become mindful of unnecessary context switches that erode my productivity. As a new mom returning to work in an unfamiliar format (WFH), I get massive morale boosts from the improvement in my productivity and feel much more confident in my ability to do my job during a stressful time!

As noted above, even just being mindful of the unnecessary context switching (or incoming distractions) can make a meaningful change in one’s workday. We also saw that for engineers who opted into the feature received more focused time in their IDE while still sending the same volume of messages overall (which implies that we are simply delaying, not reducing, communication).

The Future

While developing this feature we also looked at how many messages are sent with the special DND-override keyword (@notify) during focus blocks. It turns out that less than 5% of work communication is actually urgent enough for the sender to interrupt the receiver — yet most chat applications interrupt the receiver with every push notification.

Thus for Focus Blocks and Auto-Focus, we essentially blocked 95% of push notifications yet did not change overall sends. This implies that a large majority of communication can be delayed with no adverse effects on communication and provide increased productivity through less context switching. Hopefully this insight can help nudge chat applications towards being more asynchronous vs interruptive (especially when in deep focus).

There’s also no reason why this algorithm can’t be generalized between more IDEs (like XCode) to control DND on platforms (like Slack or macOS). We hope that this small prototype can spark discussion and eventual integrations for more people in our industry.

If you are interested in joining one of our engineering teams, please visit our careers page.

RELATED ARTICLES

Check out more articles about engineering