A look inside the Quip engineering team
Editor's note: This was originally posted on Quora, as an answer to the question “What's it like to work at Quip as a software engineer?” Below is the answer to that question, authored by Quip engineer Shrey Banga.
Quip is a unique company. I felt this almost immediately after I started in January 2016, but it took me a while to articulate why. So here goes:
Quip was founded by Bret Taylor and Kevin Gibbs, who brought in a lot of wisdom from their experiences at companies like Google, Facebook, and Friendfeed. As a result, in many ways Quip functions like a mature tech company — most people work about 8 hours a day, our on-call rotations are exceptionally peaceful and most of our tools are quite sophisticated for a startup. However, they also made some choices that don't fit the mold of a typical big tech company — code reviews are not mandatory, engineers rarely have meetings, and the org structure is much flatter. With these choices, Quip feels more mature than a typical startup, but without completely sacrificing the agility of a small team.
Most of the work of building Quip is done on Quip. We maintain prioritized lists of tasks that require engineering or design work grouped by themes. We have task lists for parts of the product, infrastructure, and new projects (e.g. “Jetson Task List” for the recent redesign). Then engineers claim tasks and discuss product or technical trade-offs within the document's conversation panel or comments for everyone else to see and learn from. We use Quip chat for other communication, such as announcements, asking for help, logging production changes, and starting pun threads. That way, we are constantly dogfooding our own product, which helps us gather tons of feedback before a change goes out into the world.
One of the unique skills I noticed in Quip's engineers was the habit of building tools that save time. Over the years, we have ended up with a lot of highly sophisticated tools, such as:
xray: This is a tool to collect streaming logs from various services all around our infrastructure. This is really helpful when debugging an issue that might arise anywhere during a request that relies on a lot of services. We add logging statements in the codebase that log to xray. This tool can then connect to all the hosts in production and extract parts of these logs filtered by service type, path regexes, server regexes, etc.
Model Browser: Our JS clients store model objects and use them to render the UI on the web and desktop apps. The model browser intelligently renders the protocol buffers backing these model objects, which is really helpful when debugging client-side issues.
Diagnostic Reports: When a client-side exception occurs in Quip, we send a “diagnostic report” back to our servers, tagged with a lot of useful information like the current document state, the stack trace of the exception, and the hash of the JS being used by the client (so we can unmangle the stack trace). This is incredibly useful in tracking down and fixing unusual bugs that only occur in very specific circumstances.
Error clustering: When a diagnostic report or a server-side error is reported, we cluster it based on some metadata. Then when a new cluster is created, we know we likely introduced a new bug in the system. These are typically noticed and fixed during the daily release process.
Redaction system: Sometimes we need to look at the contents of documents, messages, etc. to debug issues. While we always ask for user permission before doing this, we still want to minimize the amount of content that gets exposed to us. So we built a library to replace user generated content with unicode squares to allow us to see the document structure without seeing the content.
Apart from just building tools, engineers often iterate on existing tools to ensure that they remain relevant and useful as our needs change. This is often just a matter of small tweaks, but keeping tools from going out of disrepair has a huge impact on the productivity of the developers who rely on these tools.
As an example of how often new tools get built, Mihai built a system for automatically fixing documents that ended up in a bad state by writing “fixers” and triggering them to run on documents when certain diagnostic reports were triggered. This was in response to an issue where I didn't fully migrate all the old Quip tables over to spreadsheets before deleting code that supported old tables. This tool saved us a ton of effort of playing whack-a-mole with old documents, plus it will be useful in fixing documents that end up in a bad state due to other reasons.
Quip's codebase is frequently refactored to make sure we are using the best tools and avoiding code rot. For example:
Python 3: We recently migrated our codebase to Python 3, which among other things let us replace our homegrown co-routine library with async/await. Not only did this improve performance of our production servers, it also made it easier for new engineers to get productive in our codebase by moving to a standard tool.
Docker: When I first started, getting a local instance of Quip working involved stepping through a giant script that would frequently break as peoples’ development environments changed. This was a frustrating experience for new hires who were especially unfamiliar with the environment. This was also subtly different from our production environment, meaning some bugs could only be reproduced in production. So we recently migrated over to using Docker for local development, which made life a lot simpler for development and debugging.
React: We migrated over to React in 2015 along with a custom client-side object model that lets us iterate on our UI quickly. This involved adding a custom Closure Compiler pass for React, along with forking the React source to prevent minification of certain properties by the Closure Compiler.
A remarkable aspect of these projects is that we finished them very quickly. This was a result of carefully choosing which refactors to do and then fully committing to the work required to do these, including cleanups so we are not left maintaining multiple systems for a long time.
If I had to pick one thing that sets Quip's engineering apart from most teams its size, I'd say it's the level of maturity in the team when it comes to trade-offs that every startup has to make.
When working at a startup, it's easy to get in the mode of picking the easiest — and often hackiest — way of doing something to save time. However, this decision often underestimates the cost of maintaining a hacked-together system. Watching Quip engineers spend the extra effort of building robust systems made me realize that you can build a rapidly evolving product without sacrificing code quality.
We make similar trade-offs in our release process. We only do server-side releases once a day from Monday to Thursday to make sure the product is stable enough for our users who rely on Quip for critical work. We do not do releases on Friday to avoid causing issues that would require engineers to work on weekends.
Similarly, our on-call system is designed to avoid paging people for non-critical things outside work hours. We also strive to fix things in a more permanent way to avoid repetitive firefighting, and push for re-engineering systems that cause frequent issues.
A common theme in these decisions is to avoid the pitfall of glorifying long working hours just because we are a startup. That kind of culture frequently leads to burnout, so we bias towards a sustained cadence of work where everyone helps each other instead of working long hours on lone wolf projects.
People at Quip are deeply aware of the lack of diversity in tech and try hard to fix it. We started the Quip Diversity Scholarship last year (and just announced the second one!) and hosted a number of events to help people in underrepresented groups get access to technical mentorship. Some of us also mentor women at Hackbright, which I would personally recommend for anyone looking to mentor people.
Finally, we spend a significant amount of time discussing every candidate who interviews at Quip, often reflecting on our unique engineering culture and how we want to maintain it. We tend to value strong engineering skills over pure academic smartness and tend to avoid arrogance, however strong the candidate may be.
All of this sounds pretty serious, but we are actually a warm and funny bunch. While we have our lives outside of work, we tend to do a lot of activities together, such as board game nights, inner tubing trips, ski trips, boba runs, paint nights, movie nights, climbing, going out to dinner together, floating etc. And sometimes a beautiful pun thread is all you need to make your day:
Did we mention we're hiring?
If this sounds good, come join us! Quip is hiring for several roles in engineering, including front-end, mobile, growth, infrastructure, and an engineering manager.