When Steve Crocker wrote the very first RFC in 1969 on ARPANET, the small network of computers that connected four American research universities, he did so to avoid “sounding presumptuous” when compiling notes from a meeting of graduate students and staff. He titled his memo “Request for Comments,” or “RFC” for short. Other members of the group soon followed suit, writing RFC memos of their own, printing them out, and mailing the documents to one another in the era before email.
While some organizations might reach an agreement by decree of engineering leadership, RFCs provide a more egalitarian approach.
Over 50 years later, the RFC format continues to be computer scientists’ preferred method of introducing new ideas, behaviors, and specifications to the workings of the internet. So much so, in fact, that every official Internet Standard, a specification of an internet technology or methodology, has started off as an RFC that was later adopted by the Internet Engineering Task Force, the organization that creates and promotes these standards. The RFC process is now used by a growing number of open-source projects, including prolific frameworks and languages such as Ember, React, Vue, Swift, and Rust, to propose, implement, and plan new features. Some companies, including Artsy and Uber, have even adopted the process for introducing technical—and sometimes cultural—changes internally.
Suffice it to say, the RFC process is a tried-and-true methodology used by many in the industry. It can help us communicate effectively and share important knowledge and context within a team. And when it comes to planning changes to a codebase, product, or organization, it can support us in coming to a consensus around why certain problems need to be tackled and how we can best address them. While some organizations might reach an agreement by decree of engineering leadership, RFCs provide a more egalitarian approach.
A case study in adopting RFCs
Also in this issue
Open-source excursions: The poetry of planning
Reflections on the value of a planning process that emphasizes transparency, empathy, and the people behind the products.
Building software can be an expensive, time-consuming task. Using our resources, energy, and precious minutes to solve the right things, at the right times, in the right ways, can help ensure we’re being as efficient as possible—and we can leverage the consensus-building powers of RFCs to achieve that.
I recently implemented the RFC structure at a relatively small, open-source, globally distributed startup where I was spearheading an effort to overhaul the product engineering and planning process. With a fast-growing engineering team, an under-resourced product team, and no standardized approach to technical decision-making, we struggled to allocate time and resources in an organized and transparent manner. This was taking a toll on the engineering culture and product development process. We needed a better way to gather input, provide clarity, and build consensus without reinventing the wheel.
Noticing parallels between our work and that of open-source software projects relied upon by production apps and built by maintainers and contributors all over the world, we opted to take a page from the open-source book and implement the RFC process internally. As we adopted and refined our approach, we found we could make more informed and democratic judgments about how to apportion resources and align on priorities.
When to go the RFC route
From issue 15
The future of work is written
Exploring the opportunities of asynchronous communication and the (conscientiously) written word.
Whether the RFC process makes sense for your team depends on your organization’s structure, product development processes, and existing decision-making frameworks. And as with any methodology, it comes with trade-offs to consider.
The RFC process compels us to reflect on why a problem or idea matters and how we should solve and plan for it. This takes time. Writing up a proposal, requesting comments, and engaging with and addressing those comments (usually more than once) can be slow going. Some folks may resist it, preferring a faster or more familiar process. RFCs also push us to communicate extensively in writing, which can be daunting to some. And they require everyone to be involved in the surrounding discussions—after all, writing a long and well-thought-out RFC doesn’t mean much if no one reviews or provides feedback on it. If your organization already has a relatively streamlined way to handle major changes, pivoting to a completely new process might not make much sense.
But for the somewhat small, distributed engineering team I mentioned, setting up the skeleton of a new RFC process proved to be a suitable and mostly straightforward task. I followed the example set by open-source projects and created a GitHub “rfcs” repository, including a directory for accepted RFCs and a basic template for anyone to use when authoring a new one.
In our first few months using RFCs, we started to see gaps in the template, documentation, and approval process, and it took a few adjustments before it really started to gel with the engineering organization’s workflows and structure. (Don’t be surprised if you have to tweak the process a few times before it feels right for your team.) But once we got it up and running, folks started engaging with the process, asking questions, and weighing in on discussions more openly and enthusiastically than before.
Refining the RFC template
Also in this issue
An IC’s guide to roadmap planning
How individual contributors can leverage their unique perspective to advance alignment and clarity of vision.
An RFC template is often structured with a few basic sections: a summary of a proposed change, a motivation or problem statement that outlines why the change is important, a list of potential drawbacks that might result from the change, and a section on the design and implementation details. This is how our template started out, too. But over time, it grew to accommodate the idiosyncrasies of our product and engineering processes.
For example, in order to help engineering leadership more accurately estimate how many tasks the team could tackle during a given planning period, we added two more sections: one for the estimated “size,” or number of weeks required to complete the proposed change, and one to specify relevant or required skills and teams so we could better match engineers to tasks in a work cycle. We also added a section called “definition of done” to help reduce scope creep, plus a section for unsolved questions. This ended up lowering the barrier to entry, since the RFC author no longer had to worry about having every detail figured out from the get-go.
Each section of the template included guiding questions to help the RFC’s author think critically about the change they were proposing, why it mattered, what might be complicated about it, and who or what it might impact. (Our template ended up being quite extensive, but you could certainly set up an RFC process with a simpler structure.) Starting with a basic blueprint and iterating on it over time was a helpful way to kick-start the new process while also giving us room to fill in the blanks and continue to fine-tune our approach.
RFCs at work
Once these rudimentary pieces were in place, I wrote our first RFC in the form of a GitHub pull request proposing that the team adopt the RFC process. (Very meta!) Approaching this significant change by dogfooding the process itself turned out to be a powerful way to secure buy-in from stakeholders. Not only did it show others what the process would look like in action, but it also helped us identify potential pain points up front. For example, we realized how frustrating it was to manually manage the formatting and naming of newly created RFCs, so a small group of engineers wrote a nifty setup script that made each new RFC conform to the same format and filename structure.
Also in this issue
Software development as a wicked problem
An exploration of the foundational complexities of building software at scale—and why they often distill into human, rather than technical, challenges.
After writing that first RFC, I requested reviews from the entire engineering team via GitHub, just like you would solicit feedback on a PR. Team members quickly began to weigh in, asking questions and leaving comments that pointed out possible snags we might face down the road. Through asynchronous discussion, we made important process determinations together: Who reviews RFCs, and how? How much detail does an RFC need to have before it’s ready to be implemented by an engineer? How are RFCs prioritized, and how do we decide when to implement one over another?
The answers to these sorts of questions will differ based on the size and structure of your organization, but they’re important to address at the outset because they directly impact how the RFC process will function in practice. In our case, the team came to a consensus through spirited discussions, thoughtful and detail-oriented scoping, and evidence-based decision-making.
Ultimately, the entire organization rallied around RFCs and officially adopted the process. It was just what we needed to resolve the communication and decision-making bottlenecks we’d been experiencing. Colleagues from the business and customer success departments began to author RFCs of their own, which often led to impromptu collaborations with engineers to flesh out the technical requirements of a requested or much-needed feature.
Over time, we found more ways to improve the process. We created a dedicated #rfcs Slack channel to help foster conversation and ensure RFCs were reviewed at a healthy cadence. We created internal documentation so anyone could propose changes. We used a GitHub project board to help track the status of RFCs, and we leveraged labels to indicate which ones were waiting on major technical decisions, design resources, or product approval and which had been put on hold by a product leader. We leaned into automation, using GitHub actions to tag and organize RFCs on the project board. The more time we spent engaging with RFCs, the better the process became.
The magic of RFCs
Documenting big decisions transparently empowers everyone on a team to observe and participate in the surrounding discussions.
Despite its methodical and measured pace, the RFC process can, in my experience, provide many long-term benefits. By front-loading the design and implementation of a solution and having a detailed RFC document to point to, we can avoid (or at the very least minimize) the sort of back-and-forth that often occurs during code review. An RFC also helps ground the technical choices you make as an organization by compelling you to consider the rationale behind them. Past proposals form a strong foundation for future engineers, who can look to the RFC to understand why a particular feature was implemented in a certain way. If you use GitHub pull requests to house your RFCs, the discussions and comments on those proposals will live on to provide historical context.
Documenting big decisions more transparently empowers everyone on a team, regardless of skill level or experience, to both observe and participate in the surrounding discussions. And since writing is a friendly medium for distributed teams, the asynchronous nature of RFCs can contribute to a more inclusive culture that welcomes anyone to take part in the conversation.
As I watched folks discuss the merits and limitations of the RFC approach in PR comments on that very first proposal, I was reminded of what the best code reviews can feel like: a mind meld, a group of people coming together to iterate and improve upon an idea through vibrant, productive discussions. Implementing the RFC process helped close the gaps in a previously lacking product development process, encouraging methodical definitions of and approaches to product problems. It left us ready to put our heads down and focus on building the feature we’d agreed upon—the right solution, at the right time, in the right way.