Saltar al contenido

Cómo escribir RFCs técnicos efectivos

Cómo redactar RFCs que impulsen decisiones técnicas claras: estructura, calibración de la audiencia, análisis de alternativas y consenso asíncrono.

5 min de lectura
Una plantilla de documento RFC con secciones de contexto, propuesta, alternativas y registro de decisión

Un RFC (Request for Comments) es un documento estructurado que propone una decisión técnica e invita a recibir comentarios antes de comenzar la implementación. Obliga al autor a pensar el problema con rigor, saca a la luz las inquietudes de las partes interesadas desde el principio y deja un registro permanente de por qué se tomaron las decisiones.

El costo de escribir un RFC se mide en horas. El costo de no escribirlo —construir algo equivocado, descubrir problemas de integración a mitad de sprint o tomar decisiones que solo una persona entendió— se mide en semanas o meses.

Cuándo escribir un RFC

No todos los cambios necesitan un RFC. Agregar una función utilitaria, por ejemplo, no lo requiere. Pero cualquier cambio que afecte a varios equipos, introduzca infraestructura nueva, modifique una abstracción central o sea difícil de revertir sí debería tener uno.

tstypescript
// Decision framework: does this change need an RFC?
interface ChangeAssessment {
  affectsMultipleTeams: boolean;       // Cross-team coordination needed
  hardToReverse: boolean;              // Database schema, API contract, etc.
  newInfrastructure: boolean;          // New service, new database, new queue
  changesCorAbstraction: boolean;      // Auth system, data model, caching layer
  significantCostOrRisk: boolean;      // Large effort, performance implications
  controversialApproach: boolean;      // Multiple valid approaches, strong opinions
}
 
function needsRFC(change: ChangeAssessment): boolean {
  // If any two of these are true, write an RFC
  const factors = Object.values(change).filter(Boolean);
  return factors.length >= 2;
}
 
// Examples
needsRFC({
  affectsMultipleTeams: false,
  hardToReverse: false,
  newInfrastructure: false,
  changesCorAbstraction: false,
  significantCostOrRisk: false,
  controversialApproach: false,
}); // false — just do it
 
needsRFC({
  affectsMultipleTeams: true,
  hardToReverse: true,
  newInfrastructure: true,
  changesCorAbstraction: false,
  significantCostOrRisk: true,
  controversialApproach: true,
}); // true — definitely write an RFC

Estructura de un RFC

Un RFC bien estructurado facilita que quienes lo revisan entiendan el problema, evalúen la propuesta y den comentarios concretos. A continuación, una plantilla que funciona en la mayoría de las organizaciones de ingeniería.

markdownmarkdown
# RFC-042: Migrate User Sessions from Redis to DynamoDB
 
**Author:** Jane Smith
**Status:** Under Review
**Created:** 2022-02-15
**Decision Deadline:** 2022-03-01
 
## Summary
One paragraph that explains the proposal at a high level.
A reader should understand what you want to do after reading this section.
 
## Motivation
Why are we doing this? What problem does it solve?
Include data: error rates, latency percentiles, cost numbers.
 
## Current State
How does the system work today?
Include a diagram if the architecture is complex.
 
## Proposal
The detailed technical plan. What changes, how it works,
and what the migration path looks like.
 
## Alternatives Considered
At least two alternatives with honest pros and cons.
This section is the most important for building trust.
 
## Risks and Mitigations
What could go wrong? How will we detect it? What's the rollback plan?
 
## Open Questions
Things you genuinely don't know yet. Invite specific feedback here.
 
## Decision
(Filled in after the review period)
What was decided, by whom, and why.

Cómo redactar la sección de motivación

La sección de motivación es donde fallan la mayoría de los RFCs. Los autores saltan directo a la solución sin explicar antes por qué el estado actual es insuficiente. Quienes revisan el documento y no comparten el contexto del autor no van a entender por qué el cambio importa.

tstypescript
// ❌ Weak motivation — vague and assertion-based
const weakMotivation = `
  Redis is not a good fit for user sessions.
  We should use DynamoDB instead because it's more scalable.
`;
// Reviewer thinks: "Redis works fine for sessions. Why change?"
 
// ✅ Strong motivation — specific, data-driven, problem-focused
const strongMotivation = `
  Our Redis session store is hitting scaling limits:
  
  - P99 latency has increased from 5ms to 45ms over the last quarter
    as session count grew from 500K to 2.1M (chart: link)
  - We've had 3 incidents in the last month where Redis OOM killed
    caused session loss for ~12K users each time
  - The single-node Redis setup has no replication; failover requires
    manual intervention and ~8 minutes of downtime
  - Monthly cost: $1,200/mo for an r6g.2xlarge instance that's at 87%
    memory utilization with no headroom for growth
  
  We expect session count to reach 5M by Q4 based on current growth
  trends (appendix A). The current architecture cannot support this.
`;
// Reviewer thinks: "Clear problem. Let me see the proposed solution."

La sección de alternativas

La sección de alternativas es la parte más importante de un RFC para generar confianza en quienes lo revisan. Cuando demuestras que consideraste honestamente varios enfoques —incluida la opción de no hacer nada— quienes revisan saben que hiciste bien la tarea.

tstypescript
// Always include "Do Nothing" as an alternative
interface Alternative {
  name: string;
  description: string;
  pros: string[];
  cons: string[];
  estimatedEffort: string;
  whyNotChosen: string;
}
 
const alternatives: Alternative[] = [
  {
    name: 'Do Nothing',
    description: 'Keep the current Redis single-node setup',
    pros: [
      'Zero engineering effort',
      'No migration risk',
    ],
    cons: [
      'OOM incidents will increase as sessions grow',
      'P99 latency will continue to degrade',
      'Manual failover remains a risk',
    ],
    estimatedEffort: '0 weeks',
    whyNotChosen: 'Growth projections make this untenable within 2 quarters',
  },
  {
    name: 'Redis Cluster',
    description: 'Migrate to a Redis Cluster with 3 primary + 3 replica nodes',
    pros: [
      'Familiar technology — team knows Redis',
      'Horizontal scaling via hash slots',
      'Automatic failover with Sentinel',
    ],
    cons: [
      'Operational complexity increases significantly',
      'Cross-slot operations not supported (affects bulk session ops)',
      'Still requires manual capacity planning',
      'Estimated cost: $3,600/mo for 6-node cluster',
    ],
    estimatedEffort: '3 weeks',
    whyNotChosen: 'Higher operational burden than DynamoDB for similar cost',
  },
  {
    name: 'DynamoDB (Proposed)',
    description: 'Migrate sessions to DynamoDB with on-demand capacity',
    pros: [
      'Fully managed — no operational overhead',
      'Auto-scales to any traffic level',
      'Built-in TTL for session expiry',
      'Multi-AZ replication by default',
      'Pay-per-request pricing scales with actual usage',
    ],
    cons: [
      'Team needs to learn DynamoDB data modeling',
      'Migration requires dual-write period',
      'Slightly higher per-request latency (single-digit ms vs sub-ms)',
    ],
    estimatedEffort: '4 weeks',
    whyNotChosen: 'This is the proposed approach',
  },
];

Cómo recopilar comentarios de forma efectiva

Un RFC que nadie lee durante dos semanas no le sirve a nadie. Pedir comentarios de forma activa a las personas adecuadas en el momento adecuado es lo que hace que el proceso funcione.

tstypescript
// ❌ Passive feedback request
const passiveFeedback = 'Please review this RFC and leave comments.';
// Result: no one reads it, deadline passes, author assumes consensus
 
// ✅ Targeted feedback request with specific questions
const activeFeedback = {
  to: [
    { name: 'Platform Team', ask: 'Is the DynamoDB capacity estimate realistic?' },
    { name: 'Security Team', ask: 'Any concerns with session data in DynamoDB?' },
    { name: 'Backend Lead', ask: 'Does the dual-write migration plan have gaps?' },
  ],
  openQuestions: [
    'Should we use on-demand or provisioned capacity for the first month?',
    'What is the acceptable data loss window during migration cutover?',
    'Do we need to preserve session history, or can we start fresh?',
  ],
  deadline: '2022-03-01',
  decisionMaker: 'Staff Engineer — Platform',
};

Del RFC al registro de decisión

Una vez terminado el período de revisión, el RFC se convierte en un registro de decisión. Documenta qué se decidió, el razonamiento detrás y cualquier modificación que haya surgido del proceso de revisión.

tstypescript
interface DecisionRecord {
  rfcId: string;
  decision: 'approved' | 'rejected' | 'deferred';
  decisionDate: string;
  decisionMaker: string;
  summary: string;
  modificationsFromReview: string[];
  dissent: string[];     // Disagreements recorded for future reference
  reviewParticipants: string[];
}
 
const decision: DecisionRecord = {
  rfcId: 'RFC-042',
  decision: 'approved',
  decisionDate: '2022-03-01',
  decisionMaker: 'Jane Smith (Staff Engineer)',
  summary: 'Approved migration to DynamoDB with on-demand capacity',
  modificationsFromReview: [
    'Added 2-week dual-write period (originally proposed 1 week)',
    'Added rollback trigger: if DynamoDB P99 > 20ms, revert to Redis',
    'Security review: encrypt session data at rest using KMS',
  ],
  dissent: [
    'Backend Lead preferred Redis Cluster for team familiarity — noted ' +
    'but overruled due to operational cost analysis',
  ],
  reviewParticipants: [
    'Platform Team (3 reviewers)',
    'Security Team (1 reviewer)',
    'Backend Lead',
  ],
};

Puntos clave

  1. Escribe RFCs para cambios difíciles de revertir, que involucren a varios equipos o que sean controvertidos — no todo necesita uno, pero sí cualquier cosa con un radio de impacto considerable
  2. Empieza por la motivación — los planteamientos del problema respaldados por datos generan confianza en quienes revisan y justifican la inversión de ingeniería
  3. Incluye siempre alternativas — evaluar con honestidad la opción de "no hacer nada" y al menos un enfoque alternativo demuestra un pensamiento riguroso
  4. Dirige tus pedidos de comentarios — hazle preguntas concretas a personas concretas en lugar de difundir un genérico "por favor revisen"
  5. Define una fecha límite para la decisión — los períodos de revisión abiertos generan demoras indefinidas; ponle un límite de tiempo a la discusión
  6. Registra la decisión y los desacuerdos — quienes trabajen en el proyecto en el futuro necesitan entender no solo qué se decidió, sino por qué y qué concesiones se aceptaron
Wilfredo Rujel

Wilfredo Rujel

Ingeniero de Software Full Stack

Compartir esta publicaciónX