- Published on
The Complete Guide to Technical Writing in English: RFC, ADR, and Design Doc Patterns
- Authors
- Name
- Introduction
- 1. Types and Purposes of Technical Documents
- 2. RFC Structure and Key Expressions
- 3. ADR Templates and Practical Writing
- 4. Design Doc Structure: Google/Uber Style
- 5. English Expression Patterns for Technical Documents
- 6. Code Review Comment Expressions
- 7. Detailed Comparison: RFC vs ADR vs Design Doc
- 8. Common Mistakes and Corrections
- 9. Additional Template Examples
- 10. Technical Document Writing Checklist
- Summary: Core Principles of Technical Writing

Introduction
Software engineers spend only 30-40% of their working time actually writing code. The rest goes to design discussions, code reviews, and documentation. In global engineering organizations, the ability to write clear technical documents in English is a decisive factor in career growth. Companies like Google, Meta, Uber, and Stripe have deeply ingrained cultures where engineers write technical documents and gain team consensus before writing any code.
The three primary forms of technical documentation -- RFC (Request for Comments), ADR (Architecture Decision Record), and Design Doc -- each serve distinct purposes with different structures. This guide clearly distinguishes these document types, provides the key English expression patterns used when writing them, and offers practical templates you can adapt immediately.
1. Types and Purposes of Technical Documents
Key Differences Between RFC, ADR, and Design Doc
| Aspect | RFC | ADR | Design Doc |
|---|---|---|---|
| Purpose | Collect team feedback on a new proposal | Record and preserve architecture decisions | Achieve consensus on detailed technical design |
| Length | 2-5 pages | 1-2 pages | 5-20 pages |
| Lifespan | Archived after approval/rejection | Permanently preserved (history) | Living document during project |
| Audience | Broad (team, organization) | Current and future team members | Implementation team and reviewers |
| Timing | Idea/proposal stage | Immediately after a decision | Just before implementation |
| Core Question | "Is this the right direction?" | "Why did we make this decision?" | "How will we implement this?" |
When to Use Each Document
- RFC: When proposing new technology adoption, process changes, or organization-wide standards
- ADR: When recording tech stack selections, database migrations, API versioning strategies, or other key decisions
- Design Doc: When planning new feature implementation, system architecture changes, or large-scale refactoring
2. RFC Structure and Key Expressions
Standard RFC Section Structure
1. Title / RFC Number
2. Status: Draft | In Review | Accepted | Rejected | Superseded
3. Author(s)
4. Date
5. Summary / Abstract
6. Motivation / Problem Statement
7. Detailed Proposal
8. Alternatives Considered
9. Risks and Mitigations
10. Open Questions
11. References
Template 1: Full RFC Template
# RFC-042: Migrate to Event-Driven Architecture for Order Processing
**Status:** In Review
**Author:** Jane Kim
**Date:** 2026-03-10
**Reviewers:** Backend Team, Platform Team
## Summary
This RFC proposes migrating the order processing pipeline from a synchronous
REST-based architecture to an event-driven architecture using Apache Kafka.
The goal is to improve system resilience and reduce coupling between services.
## Motivation
The current synchronous order processing pipeline has the following limitations:
- **Single point of failure**: If the payment service is down, the entire
order flow is blocked.
- **Tight coupling**: Adding a new step (e.g., fraud detection) requires
modifying multiple services.
- **Scalability bottleneck**: Peak traffic (Black Friday) causes cascading
timeouts across services.
## Detailed Proposal
We propose introducing Kafka as the central message broker with the following
topology:
- Order Service publishes `OrderCreated` events
- Payment Service subscribes to `OrderCreated` and publishes `PaymentProcessed`
- Inventory Service subscribes to `PaymentProcessed`
- Notification Service subscribes to all terminal events
### Migration Strategy
Phase 1: Dual-write (weeks 1-4) - Both sync and async paths active
Phase 2: Shadow mode (weeks 5-8) - Async primary, sync for validation
Phase 3: Cutover (weeks 9-10) - Async only, sync deprecated
## Alternatives Considered
### Alternative A: gRPC with Circuit Breaker
- Pro: Lower latency for happy path
- Con: Does not address fundamental coupling issue
### Alternative B: AWS Step Functions
- Pro: Managed service, less operational overhead
- Con: Vendor lock-in, limited throughput at scale
## Risks and Mitigations
| Risk | Likelihood | Impact | Mitigation |
| ------------------------ | ---------- | ------ | ------------------------------ |
| Message ordering issues | Medium | High | Partition key by order ID |
| Consumer lag during peak | Low | Medium | Auto-scaling consumer groups |
| Data consistency | Medium | High | Saga pattern with compensation |
## Open Questions
1. Should we use Kafka Connect for database CDC, or custom producers?
2. What is the acceptable end-to-end latency for order confirmation?
## References
- Internal: Design Doc for Kafka Cluster Setup (link)
- External: "Designing Event-Driven Systems" by Ben Stopford
Key RFC English Expression Patterns
Opening a proposal:
"This RFC proposes [verb-ing]..."
"The goal of this proposal is to [verb]..."
"We are seeking feedback on [noun/gerund]..."
Explaining motivation:
"The current approach has the following limitations..."
"This change is motivated by..."
"We have observed that..."
Comparing alternatives:
"We considered [N] alternatives before arriving at this proposal."
"While [Alternative A] addresses [problem], it falls short in [area]."
"The primary trade-off of this approach is..."
3. ADR Templates and Practical Writing
Core Principles of ADR
ADRs should be short and clear. The original format proposed by Michael Nygard consists of five sections: Title, Status, Context, Decision, and Consequences. The key principle is to record decisions so that future team members can understand why a decision was made.
Template 2: Nygard-Style ADR
# ADR-017: Use PostgreSQL as the Primary Database
## Status
Accepted (2026-03-10)
## Context
We are building a new order management system that requires:
- ACID transactions for financial data integrity
- Complex queries with JOIN operations across multiple tables
- JSON support for flexible product metadata
- Strong ecosystem of ORMs and tooling
The team has experience with both PostgreSQL and MySQL. We also evaluated
NoSQL options (MongoDB, DynamoDB) for their scalability characteristics.
## Decision
We will use PostgreSQL 16 as the primary database for the order management
system.
Key factors in this decision:
- Native JSONB support eliminates the need for a separate document store
- Row-level security aligns with our multi-tenant architecture
- pg_partitioning handles our anticipated data growth (100M+ rows/year)
- The team has 3 engineers with deep PostgreSQL expertise
## Consequences
### Positive
- Unified data layer reduces operational complexity
- Strong consistency guarantees simplify application logic
- Rich extension ecosystem (PostGIS, pg_trgm) enables future features
### Negative
- Horizontal scaling requires careful planning (read replicas, partitioning)
- Higher memory requirements compared to MySQL for equivalent workloads
- Team must invest in PostgreSQL-specific performance tuning knowledge
Template 3: MADR (Markdown Architectural Decision Records) Style
# Use React Server Components for the Dashboard
## Context and Problem Statement
The dashboard currently uses client-side rendering (CSR) with React SPA.
Initial load times exceed 4 seconds on mobile devices, and SEO is not
possible for public-facing dashboard pages. We need to decide on a rendering
strategy that improves performance while maintaining interactivity.
## Decision Drivers
- Page load time must be under 2 seconds on 3G networks
- SEO required for public dashboard pages
- Developer experience should not significantly degrade
- Must be compatible with our existing component library
## Considered Options
1. React Server Components (RSC) with Next.js App Router
2. Static Site Generation (SSG) with Incremental Static Regeneration
3. Server-Side Rendering (SSR) with streaming
## Decision Outcome
Chosen option: "React Server Components with Next.js App Router" because
it provides the best balance of performance, SEO, and developer experience.
### Positive Consequences
- 60-70% reduction in client-side JavaScript bundle
- Automatic code splitting at the component level
- Server-side data fetching eliminates client-side waterfalls
### Negative Consequences
- Learning curve for the team (estimated 2-week ramp-up)
- Some third-party libraries are not yet RSC-compatible
- Debugging server/client boundary issues can be challenging
Key ADR English Expressions
"In the context of [situation], facing [concern]..."
"We decided for [option] and against [other options]..."
"We accept that [consequence] because [rationale]."
"This decision was driven by [factor]."
"The decision is [accepted/deprecated/superseded by ADR-XXX]."
4. Design Doc Structure: Google/Uber Style
Standard Structure of a Google-Style Design Doc
At Google, Design Docs are the "core tool for achieving team consensus before writing code." A good Design Doc covers design context, goals, detailed design, and alternative analysis.
1. Title and Metadata (authors, reviewers, status, last updated)
2. Overview / TL;DR (1 paragraph summary)
3. Context / Background
4. Goals and Non-Goals
5. Detailed Design
- System Architecture
- API Design
- Data Model
- Error Handling
6. Alternatives Considered
7. Cross-Cutting Concerns (security, privacy, monitoring)
8. Migration / Rollout Plan
9. Open Questions
10. Appendix
Template 4: Full Design Doc Template (Google Style)
# Design Doc: Real-Time Notification Service
**Authors:** Jane Kim, Alex Park
**Reviewers:** Backend Lead, SRE Team, Security Team
**Status:** In Review
**Last Updated:** 2026-03-10
## Overview
This document describes the design for a real-time notification service
that delivers push notifications, in-app messages, and email digests to
users. The service will handle up to 10 million notifications per day
with a p99 delivery latency of under 500ms for push notifications.
## Context
Currently, notifications are sent inline within each microservice. This
leads to duplicated notification logic across 12 services, inconsistent
delivery behavior, and no centralized tracking of notification state.
User complaints about duplicate or missing notifications have increased
by 40% in Q4 2025.
## Goals
- Provide a unified notification API for all backend services
- Support push, in-app, and email channels with extensible architecture
- Achieve p99 delivery latency under 500ms for push notifications
- Enable user-level notification preferences and quiet hours
## Non-Goals
- Real-time chat or messaging features (separate project)
- SMS notifications (planned for Phase 2, not in this scope)
- Notification content personalization using ML (future enhancement)
## Detailed Design
### System Architecture
The notification service consists of four main components:
- **Ingestion Layer**: gRPC API that accepts notification requests,
validates payloads, and publishes to Kafka
- **Router**: Consumes events, resolves user preferences, and routes
to the appropriate channel handler
- **Channel Handlers**: Dedicated workers for push (FCM/APNs),
in-app (WebSocket), and email (SendGrid)
- **State Store**: PostgreSQL for notification metadata and delivery
status tracking
### API Design
The primary endpoint accepts notification requests:
POST /v1/notifications
Required fields: recipient_id, channel, template_id, parameters
Optional fields: priority, scheduled_at, idempotency_key
Response: notification_id, status (queued/delivered/failed)
### Data Model
Notifications table stores the core notification data:
- id (UUID, primary key)
- recipient_id (UUID, indexed)
- channel (enum: push, in_app, email)
- template_id (string)
- status (enum: queued, processing, delivered, failed)
- created_at, delivered_at (timestamps)
### Error Handling
- Transient failures: Exponential backoff with jitter, max 3 retries
- Permanent failures: Dead letter queue with alerting
- Duplicate prevention: Idempotency key with 24-hour TTL in Redis
## Alternatives Considered
### Alternative 1: Use a managed service (AWS SNS + SES)
- Pro: No operational overhead, built-in scalability
- Con: Limited customization for in-app notifications, cost at scale
(estimated 3x our infrastructure cost at 10M notifications/day)
- Decision: Rejected due to cost and limited in-app support
### Alternative 2: Extend existing per-service notification logic
- Pro: No new infrastructure, incremental improvement
- Con: Does not address the root cause of duplication and inconsistency
- Decision: Rejected as it perpetuates technical debt
## Cross-Cutting Concerns
### Security
- All notification payloads encrypted at rest (AES-256)
- PII fields (email, device tokens) stored in a separate encrypted store
- API authentication via service-to-service mTLS
### Monitoring
- Dashboard: delivery rate, latency percentiles, failure rate by channel
- Alerts: delivery rate drops below 99%, p99 latency exceeds 1s
## Rollout Plan
- Week 1-2: Deploy service in staging, integration tests
- Week 3: Shadow mode (dual-write to old and new system)
- Week 4: Canary rollout to 5% of traffic
- Week 5-6: Gradual ramp to 100%, deprecate old notification code
## Open Questions
1. Should we support batch notification API for marketing campaigns?
2. How do we handle notification delivery when user is offline for
extended periods (> 7 days)?
Writing Effective Goals vs Non-Goals
Non-Goals are not simply negated goals. They are things that could reasonably be in scope but are intentionally excluded.
# Good Non-Goals
"SMS notifications (planned for Phase 2, not in this scope)"
"Real-time chat or messaging features (separate project)"
"Notification content personalization using ML (future enhancement)"
# Bad Non-Goals (too obvious)
"The system should not crash" (obvious requirement)
"We will not rewrite the entire codebase" (unrealistic alternative)
5. English Expression Patterns for Technical Documents
Proposing
| Expression | When to Use |
|---|---|
| We propose adopting... | RFC introduction |
| We recommend using... | Recommendations in conclusions |
| We should consider... | Presenting alternatives |
| One possible approach is to... | Design alternative discussions |
| X is the best fit for our requirements because... | Justifying a choice |
Comparing
| Expression | When to Use |
|---|---|
| B outperforms A in terms of... | Performance comparisons |
| Compared to X, this approach... | Alternative comparisons |
| There are trade-offs between... | Trade-off analysis |
| X has a clear advantage over Y in... | Specific aspect comparison |
| X and Y are comparable in terms of... | Performance parity |
Concluding
| Expression | When to Use |
|---|---|
| Therefore, we have chosen to... | Final decision |
| Based on the analysis above... | Drawing conclusions |
| In summary, this design... | Wrapping up documents |
| The next steps are... | Action items |
| This proposal assumes that... | Stating assumptions |
Expressing Uncertainty
Expressing what is not yet certain is equally important in technical documents.
"We believe this approach will scale to 10M requests/day,
but this needs to be validated through load testing."
"The estimated latency improvement is 30-50%, pending benchmarks."
"This is our current best understanding; we will revisit after
the proof of concept."
6. Code Review Comment Expressions
Technical document writing skills transfer directly to code review comments. Review comments are shorter than documents, but clarity and constructive tone are critical.
Common Review Abbreviations
| Abbreviation | Full Form | Meaning | Example |
|---|---|---|---|
| LGTM | Looks Good To Me | Approval | "LGTM, ship it!" |
| NIT | Nitpick | Minor suggestion | "nit: trailing whitespace on line 42" |
| PTAL | Please Take Another Look | Re-review request | "Updated the error handling. PTAL." |
| WIP | Work In Progress | Not complete | "WIP: still need to add tests" |
| TBD | To Be Determined | Undecided | "TBD: will finalize after benchmarks" |
| ACK | Acknowledged | Agreement | "ACK, will address in follow-up PR" |
| NACK | Not Acknowledged | Disagreement | "NACK: this breaks backward compatibility" |
Constructive Feedback Patterns
# Suggestion (soft tone)
"Consider extracting this into a helper function for reusability."
# Question (seeking understanding)
"What is the rationale for using a map here instead of a slice?"
# Blocking issue (must fix before merge)
"This must be addressed before merging: the error is silently swallowed,
which could mask production issues."
# Praise (acknowledging good code)
"Nice approach! Using the builder pattern here makes the API much more
readable."
# NIT (minor improvement)
"nit: This variable name could be more descriptive. Maybe
'userNotificationPreferences' instead of 'prefs'?"
7. Detailed Comparison: RFC vs ADR vs Design Doc
| Comparison Aspect | RFC | ADR | Design Doc |
|---|---|---|---|
| Primary Purpose | Build consensus | Record decisions | Detail the design |
| Timing | Idea/proposal stage | Immediately after decision | Just before implementation |
| Primary Audience | Broad organization | Future team members | Implementation team/reviewers |
| Length | 2-5 pages | 1-2 pages | 5-20 pages |
| Key Sections | Motivation, Proposal, Alternatives | Context, Decision, Consequences | Goals, Design, Alternatives, Rollout |
| Status Management | Draft - In Review - Accepted - Rejected | Proposed - Accepted - Deprecated - Superseded | Draft - In Review - Approved - Archived |
| Update Frequency | Modified during review period | Rarely modified (immutable) | Continuously updated during implementation |
| Used By | Uber, Rust, Python (PEP) | ThoughtWorks, GitHub | Google, Meta, Amazon |
| Failure Mode | Approved without sufficient review | Missing context confuses future team | No alternatives: "just do this" |
8. Common Mistakes and Corrections
Mistake 1: Jumping Straight to the Solution Without Motivation
# Bad
"We should use Kafka for message processing."
# Good
"The current synchronous pipeline fails under peak load, causing
cascading timeouts. We propose using Kafka to decouple services
and improve resilience."
Principle: Always explain "Why" before presenting "What."
Mistake 2: Superficial Alternative Analysis
# Bad
"We considered MongoDB but decided not to use it."
# Good
"We considered MongoDB for its flexible schema support. However,
our workload is primarily relational with complex JOIN queries across
5+ tables. MongoDB would require application-level joins, increasing
code complexity and latency. Therefore, PostgreSQL better fits our
query patterns."
Principle: Provide concrete pros, cons, and rejection rationale for each alternative.
Mistake 3: Overusing Passive Voice
# Bad (excessive passive voice)
"It was decided that the service would be migrated."
# Good (active voice)
"We decided to migrate the service to the new cluster."
Principle: Both Google and Microsoft style guides recommend active voice for clarity.
Mistake 4: Vague Quantitative Claims
# Bad
"The system should be fast and handle lots of requests."
# Good
"The system must achieve a p99 latency of under 200ms and sustain
50,000 requests per second during peak hours."
Principle: Use specific, measurable metrics.
Mistake 5: Omitting Non-Goals
Leaving out the Non-Goals section in a Design Doc allows reviewers to misunderstand the scope. Explicitly stating "this is not in scope for this document" prevents scope creep.
# Non-Goals section example
"Non-Goals:
- This design does not cover the migration of historical data.
That will be addressed in a separate design doc.
- Real-time analytics on notification delivery is out of scope
for this phase."
9. Additional Template Examples
Template 5: Lightweight RFC (One-Page Format)
# RFC: Adopt Structured Logging Across All Services
**Author:** Alex Park | **Date:** 2026-03-10 | **Status:** Draft
## Problem
Our current logging is inconsistent: some services use plain text,
others use JSON. This makes log aggregation and alerting unreliable.
On average, engineers spend 2 hours per incident parsing logs manually.
## Proposal
Adopt structured JSON logging with a standardized schema across all
services. Use the following mandatory fields:
- timestamp (ISO 8601)
- level (DEBUG, INFO, WARN, ERROR)
- service_name
- trace_id
- message
## Impact
- Estimated 40% reduction in mean-time-to-detect (MTTD)
- Enables automated anomaly detection via log pattern analysis
- Requires updating 23 services (estimated 2 sprints)
## Decision Requested
Please review and comment by 2026-03-24. If no blocking concerns
are raised, we will proceed with implementation.
Template 6: ADR with History Tracking
# ADR-023: Switch from REST to gRPC for Internal Service Communication
## Status
Superseded by ADR-031 (2026-02-15)
## Context
In 2025, internal service-to-service calls used REST with JSON payloads.
As the number of microservices grew from 8 to 35, serialization overhead
and lack of type safety became significant pain points.
## Decision
We adopted gRPC with Protocol Buffers for all new internal service
communication. Existing REST endpoints were maintained for external
API consumers.
## Consequences
- 30% reduction in inter-service latency due to binary serialization
- Strongly typed contracts reduced integration bugs by 25%
- Increased complexity in debugging (binary payloads not human-readable)
- Required investment in gRPC tooling and team training
## Superseded By
ADR-031 introduced gRPC-Web for browser clients, extending this
decision to cover frontend-to-backend communication as well.
Template 7: Design Doc Migration Plan Section
## Migration Plan
### Phase 1: Foundation (Weeks 1-3)
- Deploy the new notification service to staging environment
- Set up monitoring dashboards and alerting rules
- Complete integration tests with all upstream services
### Phase 2: Shadow Mode (Weeks 4-6)
- Enable dual-write: existing system + new service
- Compare delivery rates and latency between old and new systems
- Acceptance criteria: new system delivers 99.9%+ of notifications
within p99 latency target
### Phase 3: Gradual Rollout (Weeks 7-10)
- Week 7: Route 5% of traffic to new service (canary)
- Week 8: Increase to 25% if metrics are healthy
- Week 9: Increase to 75%
- Week 10: 100% cutover, begin decommissioning old code
### Rollback Plan
- Feature flag to instantly revert to the old notification path
- Data reconciliation job to sync any missed notifications
- Rollback decision criteria: error rate exceeds 1% or p99 latency
exceeds 2 seconds for more than 5 minutes
10. Technical Document Writing Checklist
RFC Checklist
- Title describes the change in one sentence
- Motivation section describes the current problem with concrete data
- Proposal is specific enough to be implementable
- At least 2 alternatives compared
- Risks and mitigations included
- Review deadline and decision criteria specified
ADR Checklist
- Context is sufficient for understanding
- Decision is summarizable in one sentence
- Both positive and negative consequences recorded
- Status is correctly set
- References to related ADRs or RFCs included
Design Doc Checklist
- TL;DR (Overview) conveys the core idea in 30 seconds
- Goals and Non-Goals are clearly distinguished
- System architecture diagram included
- API design and data model described
- Alternative analysis is objective and unbiased
- Migration/rollout plan included
- Rollback strategy exists
- Cross-cutting concerns (security, monitoring) addressed
Summary: Core Principles of Technical Writing
- Reader-first: Identify your audience first, then provide the information they need
- Why before What: Always explain the problem and motivation before presenting the solution
- Be specific: Use quantitative, measurable metrics instead of vague descriptions
- Active voice: Write clearly with active voice constructions
- Show alternatives: Always record considered alternatives and rejection rationale
- Keep it updated: Design Docs are living documents -- reflect implementation changes
- Invite feedback: The essence of an RFC is feedback collection -- actively use Open Questions
Mastering technical writing is not about perfect grammar. It is about structuring your thoughts logically, communicating clearly, and making it easy for others to understand your reasoning. These skills are the foundation of effective engineering leadership in any global team.