How to Write a Technical RFC: Section-by-Section Guide
A section-by-section guide to technical RFCs: what each part has to establish, what reviewers look for, and where proposals stall in review.
An RFC for a critical system stalls for one of two reasons: reviewers cannot tell what problem it solves, or they cannot find the part that concerns them. Both are structural problems, and both are fixable before the first review comment lands.
Treat the RFC as a sales document. It sells one solution to four audiences with competing priorities: executives who fund the work, architects who vet the design, implementers who build it, and operators who carry the pager afterwards. Structure it so each audience finds its answer without reading the whole document, and put those answers in the order the audiences ask for them.
The Audience Sets the Order
A short, plainly written notification system RFC often clears review faster than a technically deeper proposal from a more senior author. The reason is rarely technical merit. The shorter document answers the questions stakeholders ask, in the order they ask them.
Section by section, here is what each part of a notification system RFC has to establish and what reviewers look for when they skim it. The implementation series covers the system such an RFC describes.
Executive Summary: The 30-Second Pitch
The executive summary is your elevator pitch. You have about 30 seconds to convince a busy VP or senior engineer that this document is worth their time. Here’s what works:
A Version That Works
We need to implement a robust, scalable user notification system that can handle
real-time updates, push notifications, email notifications, and in-app notifications
across our platform. This system will serve as the backbone for user engagement,
critical alerts, and feature announcements.
This summary works because it:
- States the what clearly (notification system)
- Lists specific capabilities (real-time, push, email, in-app)
- Connects to business value (user engagement, critical alerts)
- Avoids technical jargon
Common Mistakes
Weak version:
This RFC proposes implementing a microservices-based event-driven architecture
utilizing Kafka, PostgreSQL, and WebSockets to facilitate asynchronous message
delivery across multiple channels with configurable retry mechanisms.
The weak version loses executives at “microservices-based” and never explains why anyone should care. If a system can’t be explained to a product manager in one paragraph, the design probably needs more clarity.
Insider Tips
What reviewers actually look for:
- Scope clarity: Is this a complete rewrite or an enhancement?
- Business alignment: Does this solve a real problem or is it resume-driven development?
- Risk assessment: Are you being honest about complexity?
The strong version above puts user impact first and technology second. That clarity is what you fall back on during the inevitable scope creep discussions.
Problem Statement: Quantifying the Pain
The problem statement is where you build urgency. Numbers matter here - vague problems get vague timelines.
Effective Problem Framing
The notification RFC tied each pain point to something stakeholders already track:
### Current Pain Points
- Users miss important updates about their projects
- No centralized way to manage notification preferences
- Manual notification sending is error-prone and not scalable
### Business Impact
- Reduced user engagement and retention
- Increased support tickets due to missed communications
- Poor user experience leading to churn
Notice how each pain point maps to a business impact someone already tracks. Pain points written this way turn into the metrics you report against after launch, which is why the pairing is worth the extra paragraph.
Weak Problem Statements
Here’s what doesn’t work:
The current system is outdated and difficult to maintain. Engineers complain
about the codebase and adding new features is challenging.
This tells me nothing actionable. How outdated? What specific maintenance issues? Which features are blocked? Without specifics, this reads like every legacy system ever.
The Data That Matters
Strong RFCs include:
- Current metrics: “847 support tickets last month about missed notifications”
- Cost implications: “Engineers spend 15% of sprint time on manual notification tasks”
- Opportunity cost: “Three feature launches delayed due to notification limitations”
The problems you quantify up front become the success metrics later. A problem statement with numbers in it writes its own success criteria; a vague one leaves that argument for after launch, when the stakes are higher.
Proposed Solution: Balancing Vision and Specificity
This is where most RFCs go off the rails. Engineers either get lost in implementation details or stay so high-level that nobody knows what’s actually being built.
The Goldilocks Zone
The notification RFC found the perfect balance:
### System Architecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Notification │ │ Notification │ │ Notification │
│ Sources │───▶│ Engine │───▶│ Channels │
└─────────────────┘ └──────────────────┘ └─────────────────┘
### Core Components
- Event Processor: Handles incoming notification events
- Template Engine: Manages notification templates and personalization
- Rate Limiting: Prevents notification spam
This works because it:
- Shows the big picture architecture visually
- Breaks down into understandable components
- Explains what each component does, not how
Over-Engineering Red Flags
Watch out for:
- Solutions looking for problems (“We’ll use GraphQL subscriptions because they’re modern”)
- Technology bingo (“Kubernetes, Istio, Envoy, Linkerd…”)
- Premature optimization (“We’ll shard the database from day one”)
In practice, implementations often start simpler than the RFC suggests. The modular design allows adding complexity gradually: rate limiting in month three, not day one.
Technical Implementation: Concrete Enough to Estimate
This section separates the dreamers from the builders. Good technical specs are concrete enough to estimate but flexible enough to adapt.
A Schema That Plans for Operations
The RFC included a concrete schema rather than a description of one, and it was written with operations in mind:
CREATE TABLE notification_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
notification_type VARCHAR(100) NOT NULL,
template_id UUID REFERENCES notification_templates(id),
data JSONB DEFAULT '{}',
status VARCHAR(20) DEFAULT 'pending',
sent_at TIMESTAMP,
delivered_at TIMESTAMP,
read_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
What makes this effective:
- Audit trail built-in: sent_at, delivered_at, read_at timestamps
- Flexibility via JSONB: the data field absorbs requirements the RFC did not foresee
- Status tracking: essential for debugging production issues
What Changed in Production
Production reality adds:
- Index requirements often missed (compound index on user_id + status + created_at)
- Partition strategy for time-series data (monthly partitions)
- Archive strategy (moving old notifications to cold storage)
The production debugging post details how these requirements surface in practice.
API Design That Scales
Good RFCs show representative API endpoints:
POST /api/notifications/send
GET /api/notifications/user/:userId
PUT /api/notifications/:id/read
But great RFCs also consider:
- Pagination strategies for list endpoints
- Batch operations for efficiency
- Versioning strategy for future changes
- Rate limiting at the API level
Cursor-based pagination becomes necessary after offset pagination creates performance issues at scale; something the RFC could have anticipated.
Implementation Phases: Realistic Timeline Management
This is where optimism meets reality. Every RFC underestimates timelines, but good ones underestimate less catastrophically.
Phases That Made Sense
### Phase 1: Core Infrastructure (Weeks 1-4)
- Database schema implementation
- Basic notification engine
- In-app notification system
### Phase 2: Advanced Features (Weeks 5-8)
- Push notifications
- Template management system
- Scheduling and rate limiting
Why this phasing holds up:
- Value delivery in phase 1: users get notifications at the end of the first phase, not the end of the project
- Risk frontloading: the hard problem (real-time delivery) comes first
- Learning incorporation: phase 2 is planned loosely enough to absorb what phase 1 teaches
Timeline Reality Check
Phases slip in predictable places:
- Integration with authentication or billing runs past its estimate, because another team’s calendar is not in your plan
- Edge cases in rate limiting and retry logic surface only under load
- The final phase gets partially descoped once real usage patterns arrive
None of that is a planning failure, provided the RFC said the estimate was an estimate. The implementation series documents how to adapt a timeline while keeping stakeholder trust.
Red Flags in Timelines
Watch for:
- No buffer for discoveries (“Week 1: Implement everything”)
- No testing time allocated
- Dependency on other teams not accounted for
- “Simple integration” with external services (it’s never simple)
Technical Considerations: The Reality Check Section
This section reveals whether the authors have actually built similar systems or are just good at reading blog posts.
Scalability That Matters
The RFC got specific about scale:
### Performance Targets
- Notification delivery: < 100ms for in-app, < 5s for email
- System throughput: 10,000+ notifications per second
- Database query performance: < 50ms for preference lookups
These aren’t arbitrary numbers. They’re derived from:
- Current user base (10,000 notifications/second = peak load × 3)
- User experience research (100ms feels instant)
- Infrastructure constraints (database connection limits)
Targets vs. Measurement
Write the targets so someone can check them later, and expect at least one to be wrong:
- Delivery latency usually lands near target, because it is the number the design optimizes for
- Peak throughput usually lands under the projection, because the projection was peak load times a safety factor
- Query latency is the common miss; preference lookups need an index the RFC did not specify
A target you cannot instrument is a wish. Pair each number with the place it will be read from: a dashboard panel, a log field, a load test. The analytics and optimization post details how these targets get instrumented.
Security Considerations Reviewers Check
Good RFCs address:
- Authentication: “JWT tokens with 15-minute expiry”
- Authorization: “Role-based access with granular permissions”
- Rate limiting: “Per-user limits with exponential backoff”
- Data privacy: “PII encryption at rest, GDPR compliance”
A security incident can surface months in, when someone attempts to use the notification system for spam. A rate limiting strategy specified in the RFC prevents the platform from becoming an unwitting spam relay.
Testing Strategy: Beyond “We’ll Write Tests”
Testing sections reveal whether teams actually practice TDD or just talk about it.
Load Tests Worth Specifying
### Load Tests
- High-volume notification sending
- Concurrent user connections
- Database performance under load
- Queue processing capacity
What makes this valuable:
- Specific scenarios: not “load testing” in the abstract, but which load
- Performance criteria: clear pass/fail conditions
- Tool selection: naming the tool (k6, Gatling, Locust) instead of leaving the choice to whoever picks up the ticket
Testing Gaps to Expect
Testing sections routinely omit:
- Chaos testing for dependency failures, such as a cache or broker outage
- Cross-browser WebSocket compatibility
- Mobile app battery impact from persistent connections
- International character set handling in templates
Good RFCs acknowledge that you can’t predict every test scenario but provide a framework for discovering what you missed.
Monitoring & Analytics: The Metrics You Check Daily
Most monitoring sections list every possible metric. Good ones identify the 3-5 metrics that indicate system health.
Metrics Worth Listing
### Key Metrics
- Delivery success rate (target: 99.9%)
- Delivery time by channel
- User engagement rates
- Support ticket volume
Four metrics is roughly the limit of what a team checks daily. Everything else is noise until something breaks, at which point you go looking for it deliberately.
Alert Fatigue
The RFC suggested alerting on:
- High error rates (> 5%)
- Delivery delays (> 10s)
- System resource usage (> 80%)
What warrants an alert:
- Delivery success rate < 99% (not 95%)
- Email delivery P99 > 30s (not 10s)
- Database connection pool exhaustion (not CPU usage)
The real-time delivery post explains how to tell a genuine problem from normal variance.
Cost Analysis: The Budget Reality
This is where engineering meets business. Good cost sections acknowledge both immediate and ongoing costs.
Costs You Can Predict
### Infrastructure Costs
- Database: $200-500/month
- Message Queue: $50-150/month
- Push Notification Services: $0.50 per 1000 notifications
Line items like these hold up, because they come from published pricing.
Costs That Get Missed
The predictable line items are rarely the whole bill. What tends to be left out:
- Log ingestion and retention, which scales with how much you decide to log
- Object storage for the notification archive
- The extra read replica added once query latency slips
- Engineering time for maintenance, which is a standing cost rather than a project cost
Infrastructure line items are usually the smaller half of total cost of ownership. Name the omitted categories in the RFC even when you cannot price them; stakeholders forgive a range, not a surprise.
Projecting ROI
The RFC projected:
- 20-30% reduction in support tickets
- 5-15% increase in user retention
Ranges age better than point estimates, but only when the measurement method ships alongside them: which ticket categories count, which retention cohort, measured over what window. Without that, the conversation after launch is about definitions instead of results.
Risks & Mitigation: Honest Assessment
The best risk sections admit what the authors don’t know.
The Risk That Usually Lands
Risk: Database performance degradation with high volume
Mitigation: Proper indexing, read replicas, query optimization
Of the risks a notification RFC lists, this is the one that lands. Query latency degrades gradually, then timeouts start arriving in batches. The listed mitigation works, but indexing, read replicas, and query rewrites are weeks of work rather than an afternoon. Schedule them before the volume arrives.
Risks That Went Unanticipated
- WebSocket connection limits in the load balancer
- Template rendering performance with nested conditionals
- Time zone edge cases for scheduled notifications
- Mobile carriers blocking the SMS provider
Good RFCs acknowledge unknown unknowns and build in flexibility to handle them.
Success Criteria: Measurable Outcomes
This section is your contract with stakeholders. Make it measurable and realistic.
Criteria That Work
### Technical Success
- 99.9% notification delivery success rate
- < 100ms in-app notification delivery
- System handles 10,000+ notifications per second
These are:
- Measurable: specific numbers, not “fast” or “reliable”
- Achievable: based on comparable systems rather than wishful thinking
- Relevant: tied directly to user experience
Moving Goalposts
Criteria get renegotiated after launch, usually in the same three ways:
- The availability target drops a nine, because the last nine costs more than it returns
- Latency targets relax to the threshold users can perceive
- Throughput requirements fall to observed peak load rather than the projected one
None of that is cheating, as long as you record why a criterion changed and get stakeholder agreement on the replacement. Silent revision is what erodes trust.
What Each Audience Looks For
Different stakeholders care about different things. The recurring shape:
What VPs/Directors Look For
- Executive summary that explains business value
- Cost analysis with clear ROI
- Timeline with milestone deliverables
- Risk section that doesn’t hide complexity
What Senior Engineers Look For
- Technical implementation that shows deep understanding
- Scalability considerations based on actual metrics
- Alternative approaches and why they were rejected
- Integration points with existing systems
What Team Leads Look For
- Implementation phases that deliver value iteratively
- Testing strategy that’s actually executable
- Success criteria their team can rally around
- Monitoring approach that won’t create alert fatigue
What Security Teams Look For
- Authentication/authorization approach
- Data privacy considerations
- Rate limiting and abuse prevention
- Audit trail capabilities
What RFCs Routinely Underweight
Four areas that most templates leave thin:
Documentation Is Part of the System
The RFC becomes the primary documentation whether you plan for it or not. Structuring it as living documentation from the start pays dividends.
Migration Strategy Matters
RFCs focus on the new system and barely mention migrating off the old one. Migration is a project of its own; an RFC that skips it hands the team an unplanned one.
Operational Runbooks
The RFC should include or mandate operational runbooks. The gap becomes obvious during the first production incident, which is the worst time to notice it.
Feature Flags
Phased rollout gets mentioned; feature flags rarely do. A flag turns a bad release from a rollback into a config change.
The RFC as a Living Document
Good RFCs stay in use after approval. They evolve into:
- Architecture documentation
- Onboarding materials for new team members
- Decision logs for future reference
- Post-mortem context when things go wrong
A well-maintained RFC keeps accumulating commits after approval, one for each significant deviation from the plan.
RFC Usefulness Criteria
Here’s what separates useful RFCs from bureaucratic exercises:
Write for Multiple Audiences
Your RFC has at least four audiences: executives, architects, implementers, and operators. Structure it so each can find what they need quickly.
Be Honest About Uncertainty
The best RFCs include sections titled “What We Don’t Know Yet” or “Assumptions That Might Be Wrong.”
Include Escape Hatches
Good RFCs explain not just how to build the system but how to back out if things go wrong. This paradoxically makes approval easier.
Make Success Measurable
Vague success criteria lead to endless debates. Specific numbers force clarity about what you’re actually trying to achieve.
Show Your Work
Include enough detail that another team could implement your design, but not so much that you’re writing the code in prose.
RFC Imperfection and Trade-offs
No RFC is perfect. The notification system RFC walked through above has real gaps: it underestimates complexity, is thin on operational concerns, and is optimistic on timelines. It still does the job that matters, which is aligning stakeholders on a good-enough solution and leaving them a framework for improving it.
The RFC Paradox
A pattern holds across many organizations: the teams that write the best RFCs often need them the least. Their communication is already strong, their thinking clear, their engineering practices sound, and the document simply formalizes what they do anyway. Teams that struggle with RFCs usually have deeper problems: unclear requirements, competing visions, or technical debt that makes every solution complex. For them the RFC becomes a forcing function, which is uncomfortable and useful in equal measure.
Use the full structure when a proposal crosses team boundaries, commits budget, or is expensive to reverse. Skip it when the change touches one team and can be undone in an afternoon; a short design note on the pull request carries the same information with less ceremony. Between those two cases, write the problem statement and the success criteria, and leave the rest to the implementation.
References
- RFC Editor - The authoritative source for published RFCs, maintained by the RFC Production Center
- IETF RFC Process - Official IETF documentation on how RFCs are created, reviewed, and published
- Architectural Decision Records - adr.github.io - Community resource on ADRs, a lightweight alternative for capturing architecture decisions
- ADR Templates - Collection of ADR templates including the widely used Nygard format
- Google Engineering Practices - Google’s public documentation on engineering practices including design review processes
Related posts
Practical guidance on RFC structure, stakeholder review, and turning technical debates into decisions a team actually keeps.
Documentation debt can slow teams faster than technical debt. A guide to treating docs as critical infrastructure and scaling knowledge across engineering teams.
How Arnold Mindell's Deep Democracy principles transform technical decision-making, build psychological safety, and ensure every voice strengthens architecture.
Where RFC designs diverge from production reality, using notification systems as the worked example, and how to tell useful adaptation from architectural drift.
How AWS Dogwood adds temporal conditions to Cedar policies, lowers them back to plain Cedar, and enforces agent guardrails at the Amazon Bedrock AgentCore gateway.