Why Your Open Source Project Needs a Formal RFC Process (And How to Implement One on GitHub)
You’ve got a thriving open source project. Maybe 2,000 stars, a handful of active contributors, and a growing stream of issues and feature requests. Things feel… chaotic.
Sound familiar? It should.
The AI Coding Tool Trap: How Junior Engineers Stop Learning (And the Workflow That Fixes It)
The AI Coding Tool Trap: How Junior Engineers Stop Learning (And the Workflow That Fixes It) I’ve seen… ...
Every successful open source project I’ve touched eventually hits a wall: decision paralysis. Who decides what to build? How do you get buy-in from stakeholders? And why does every major design decision end up in a 200-comment GitHub issue thread that goes nowhere?
The answer isn’t more control. It’s better process. Specifically, a formal RFC (Request for Comments) workflow.
The API Design Playbook: What Actually Works in 2026
TL;DR: Building APIs that scale isn’t about following every rule in the book. It’s about knowing which rules… ...
Rust uses it. Kubernetes uses it. React uses it. You should too. Here’s why – and the exact steps to set it up on GitHub.
What’s an RFC – and Why Should You Care?
An RFC isn’t just a glorified GitHub issue. It’s a structured, transparent way to propose, debate, and document significant changes to your project. Think of it as a lightweight design doc that lives in your repo.
Most open source projects fall into one of two traps:
- The benevolent dictator trap: one person makes all the big calls. It scales badly and burns out the maintainer.
- Design-by-committee: 30 people argue for three weeks, and nothing ships.
A good RFC process avoids both. It gives everyone a voice but sets a clear, time-boxed path to a decision.
I’ve seen this work firsthand. We adopted an RFC process for a 10K-star orchestration tool last year. Before that, landing a new feature took 4-6 weeks of back-and-forth. After RFCs? Two weeks, max. The team in our Can Tho hub handled most of the automation – labels, templates, the whole pipeline.
The Core Components of an Open Source RFC Process
You don’t need a PhD in governance. You need three things:
- A template – so every proposal follows the same structure.
- A review workflow – labels, statuses, and deadlines.
- Documentation – a `rfcs/` directory where accepted proposals live forever.
Let’s build each one.
1. The RFC Template
Start with a markdown file in `.github/ISSUE_TEMPLATE/rfc.md`. Here’s the template we use – it’s battle-tested across 50+ accepted RFCs:
markdown
---
name: RFC
about: Propose a significant change to the project
title: "[RFC] "
labels: rfc, needs-review
assignees: ''
---
## Summary
One paragraph explaining the proposal in plain English.
## Motivation
Why is this change necessary? What problem does it solve?
## Design Proposal
Detailed technical description. Include diagrams, pseudo-code, or links to prototypes.
- **API changes**: List any new endpoints, config options, or CLI flags.
- **Performance impact**: Estimated effect on throughput/latency.
- **Backward compatibility**: Will this break existing users?
## Alternatives Considered
What else did you evaluate, and why did you reject it?
## Open Questions
What’s still uncertain? This is a healthy part of any RFC.
## Timeline
Proposed implementation phases, target milestones.
No, it’s not perfect. But it forces contributors to think before they type. That alone cuts 30% of the bikeshedding.
2. The Label and Status Workflow
On GitHub, labels are your best friend. We use these:
| Label | Meaning |
|---|---|
| `rfc` | Marks the issue as an RFC |
| `needs-review` | Open for comments |
| `under-discussion` | Maintainer has signaled it’s ready for final feedback |
| `accepted` | Approved, ready for implementation |
| `rejected` | Closed with clear rationale |
| `deferred` | Punted to a future release |
The lifecycle is simple: PR submitter creates an issue with the RFC template → maintainer adds `needs-review` → after 14 days (minimum), maintainer promotes to `under-discussion` → final decision within 7 days → close as `accepted` or `rejected`.
Automate this with a GitHub Action that pings maintainers when an RFC has been in `needs-review` for 10 days. I’ll show you that action in a second.
3. The RFC Archive
Every accepted RFC gets merged into a `rfcs/` directory at the root of your repo. Use a naming convention like `rfcs/0012-state-management-refactor.md`.
This is your project’s permanent memory. New contributors can read through past RFCs and understand *why* decisions were made. It’s gold for onboarding.
Automating the Workflow with GitHub Actions
Here’s the action that (a) reminds maintainers of stale RFCs and (b) auto-closes stale `needs-review` issues after 21 days of inactivity.
Create `.github/workflows/rfc-stale.yml`:
yaml
name: RFC Stale Check
on:
schedule:
- cron: '0 9 * * 1' # every Monday at 9am UTC
workflow_dispatch: # manual trigger for testing
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
contents: read
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-label: 'stale-rfc'
stale-issue-message: |
This RFC has been open for 14+ days without maintainer response.
Please either advance it to `under-discussion` or provide a status update.
It will be automatically closed in 7 days if no activity.
close-issue-message: |
This RFC was automatically closed due to inactivity.
Feel free to reopen with updated content.
days-before-stale: 14
days-before-close: 7
only-labels: 'needs-review'
exempt-all-assignees: true
operations-per-run: 50
This isn’t just automation. It’s a social contract. Contributors know their RFC won’t be ignored forever.
What Happens When You Skip This Process?
I’ve been maintaining a popular Python async library for about three years. Before we introduced RFCs, every major feature was born from a firehose of GitHub comments. No structure. No consensus. The voices of two loud maintainers (+1 from our remote team in Ho Chi Minh City) drowned out quieter but brilliant contributors.
The result? We shipped a breaking change that 30% of users hated. It took us six months to recover trust.
Contrast that with the Rust project. Every significant change – from async/await to the borrow checker – went through an RFC. The process isn’t perfect (it can be slow), but it’s legitimate. People feel heard, even when their proposal is rejected.
Common Objections (And Why They’re Wrong)
“It’s too bureaucratic for a small project.”
Actually, it scales down. You can run a 10-contributor project with a two-day review window. The structure saves time, doesn’t waste it.
“We already use issues – why the extra template?”
Issues are for bug reports and small enhancements. RFCs are for design decisions that affect architecture, API surface, or long-term roadmap. They’re fundamentally different.
“No one will read the RFCs; people will still argue in comments.”
That’s fine. The RFC exists as a single source of truth after the debate ends. Future contributors can reference the document instead of re-litigating the same arguments.
Real Numbers from Our Project
After six months with RFCs:
- 43% fewer “design” comments in regular issues.
- 2.1x faster decision time for major features (20 days → 9.5 days median).
- 100% of accepted RFCs had at least one non-maintainer reviewer (previously: 18%).
The last point matters most. Your project isn’t yours. It belongs to the community. An RFC process proves you trust that community to co-author the roadmap.
Getting Started: Your 7-Day Plan
- Day 1: Copy the template above into `.github/ISSUE_TEMPLATE/rfc.md`.
- Day 2: Create the label set (`rfc`, `needs-review`, `under-discussion`, `accepted`, `rejected`, `deferred`) in your repo.
- Day 3: Configure branch protection to require RFC acceptance before merging `rfcs/` changes.
- Day 4: Deploy the stale-action workflow.
- Day 5: Announce the new process in a pinned discussion or blog post.
- Day 6: Ask one contributor to submit a test RFC (like a trivial documentation improvement).
- Day 7: Walk through the RFC lifecycle together.
That’s it. You’re now running a more transparent, more scalable open source project. And you’ll never have to guess what the community thinks again.
—
Frequently Asked Questions
Do I need a separate repo for RFCs?
No. Keep them in the same repo under `rfcs/`. This keeps history tied to code changes. Some projects use a dedicated repo (like `rust-lang/rfcs`), but that’s overkill for 90% of projects.
How do I handle disagreements that go past the deadline?
Set a maximum extension period (e.g., 7 additional days). If no consensus emerges, the maintainer decides. Document the disagreement in the RFC itself. This isn’t about winning; it’s about making a decision and moving forward.
Should RFCs include implementation code?
Not necessarily. Pseudo-code or high-level API signatures are fine. The RFC is about design intent, not line-by-line implementation. Actual code belongs in a pull request that references the accepted RFC.
What if someone rejects an RFC but later changes their mind?
RFCs are immutable after acceptance – they document the decision at the time. If circumstances change, open a new RFC that supersedes the old one. This keeps the paper trail clean.