🗣️ Developer Cookbook - FASE 8: Habilidades Blandas y Liderazgo

Recetas prácticas para comunicar, liderar y gestionar equipos técnicos efectivamente


Comunicación Técnica

Receta 8.1: ADRs (Architecture Decision Records)

¿Qué es? Documentos cortos que explican por qué tomamos decisiones de arquitectura importantes. No solo el “qué”, sino el “por qué” y las alternativas consideradas.

Cuándo escribir un ADR:

Template de ADR:

# ADR-001: [Título corto de la decisión]

## Status
[Proposed | Accepted | Deprecated | Superseded]

## Context
¿Qué problema estamos resolviendo? ¿Por qué necesitamos tomar esta decisión?

## Decision
¿Qué vamos a hacer?

## Consequences
¿Qué ganamos? ¿Qué perdemos? ¿Qué trade-offs?

### Positive
- Beneficio 1
- Beneficio 2

### Negative
- Costo/limitación 1
- Costo/limitación 2

### Risks
- Riesgo 1
- Riesgo 2

## Alternatives Considered
¿Qué otras opciones evaluamos y por qué NO las elegimos?

### Alternative 1: [Nombre]
- Pros: ...
- Cons: ...
- Rejected because: ...

### Alternative 2: [Nombre]
- Pros: ...
- Cons: ...
- Rejected because: ...

## References
- Links a documentación
- RFCs relacionados
- Investigación previa

Ejemplo real:

# ADR-003: Migrar de PostgreSQL a DynamoDB para tabla de sessions

**Date**: 2024-02-20
**Status**: Accepted
**Author**: Engineering Team
**Reviewers**: CTO, Backend Lead

## Context

Nuestra aplicación web almacena sessions de usuarios en PostgreSQL.
Hemos observado:

- 500K usuarios activos mensuales
- 10M+ queries/day a la tabla sessions
- Latencia p95 de 150ms (target: <50ms)
- DB CPU al 80% durante peak hours
- Sessions table = 60% del total de queries
- Costo actual: $800/mes en RDS PostgreSQL db.m5.xlarge

El problema: Las sessions son 90% reads, no necesitan relaciones,
y están saturando nuestra DB relacional.

## Decision

Migraremos la tabla de sessions de PostgreSQL a DynamoDB.

**Scope:**
- Solo sessions (usuarios, productos permanecen en PostgreSQL)
- Mantener TTL de 30 días
- Migración gradual con feature flag (canary deployment)

**Implementation plan:**
1. Crear tabla DynamoDB con partition key = session_id
2. Dual-write: escribir en ambas DBs por 1 semana
3. Gradual read migration: 10% -> 50% -> 100%
4. Deprecar PostgreSQL sessions después de 2 semanas

## Consequences

### Positive
- Performance: DynamoDB latencia menor a 10ms (vs 150ms)
- Scalability: Auto-scaling, sin límite práctico
- Cost: $120/mes DynamoDB vs $800/mes RDS = $680/mes savings
- DB load: Libera 60% de queries en PostgreSQL
- TTL native: DynamoDB TTL automático (no necesitamos cron job)

### Negative
- No SQL queries: No podemos hacer SELECT * FROM sessions WHERE user_id = X
- Learning curve: Team necesita aprender DynamoDB
- Migration complexity: Dual-write durante transición
- Vendor lock-in: Más difícil migrar de AWS

### Risks
- Data inconsistency durante migration: Mitigado con dual-write
- DynamoDB costs spike: Mitigado con auto-scaling limits
- Rollback complexity: Mantenemos PostgreSQL sessions 2 semanas

## Alternatives Considered

### Alternative 1: Redis (ElastiCache)
**Pros:**
- Más rápido que DynamoDB (~1ms)
- Team tiene experiencia con Redis
- Fácil de implementar

**Cons:**
- Volátil (se pierde en restart a menos que uses persistence)
- Costo similar a DynamoDB pero con menos durabilidad
- Requiere clustering para HA

**Rejected because:**
Necesitamos durabilidad. Perder todas las sessions en un restart
no es aceptable. DynamoDB ofrece similar performance con mejor durabilidad.

### Alternative 2: Optimize PostgreSQL queries
**Pros:**
- No migration needed
- Zero learning curve
- Keep everything in one DB

**Cons:**
- Solo reduces latencia a ~80ms (no suficiente)
- No soluciona problema de scaling
- PostgreSQL no diseñado para este access pattern

**Rejected because:**
Optimización incremental no resuelve problema fundamental.
Sessions son key-value lookups, no necesitan SQL.

### Alternative 3: Keep as-is and scale up RDS
**Pros:**
- Zero migration effort
- Familiar technology

**Cons:**
- Costo: db.m5.2xlarge = $1,600/mes (2x actual)
- Solo patea el problema 6 meses
- No mejora latencia significativamente

**Rejected because:**
Costo prohibitivo y no sustentable. No es escalable long-term.

## References
- [DynamoDB Best Practices](https://docs.aws.amazon.com/dynamodb/)
- [Session Management at Scale - Auth0](https://auth0.com/blog/)
- Internal: `experiments/dynamodb-sessions-poc` (results summary)
- Slack discussion: #architecture-decisions (2024-02-15)

## Success Metrics
- Latencia p95 < 50ms
- $500+ monthly cost savings
- Zero data loss during migration
- <1% error rate during transition

Python tool para generar ADR:

from datetime import datetime
from dataclasses import dataclass
from typing import List

@dataclass
class Alternative:
    name: str
    pros: List[str]
    cons: List[str]
    rejected_reason: str

@dataclass
class ADR:
    """Architecture Decision Record"""

    number: int
    title: str
    status: str  # Proposed, Accepted, Deprecated, Superseded
    context: str
    decision: str
    positive_consequences: List[str]
    negative_consequences: List[str]
    risks: List[str]
    alternatives: List[Alternative]
    references: List[str]
    author: str = "Engineering Team"

    def generate_markdown(self) -> str:
        """Generar ADR en formato markdown"""

        date = datetime.now().strftime("%Y-%m-%d")

        md = f"""# ADR-{self.number:03d}: {self.title}

**Date**: {date}
**Status**: {self.status}
**Author**: {self.author}

## Context

{self.context}

## Decision

{self.decision}

## Consequences

### Positive
"""
        for pro in self.positive_consequences:
            md += f"- {pro}\n"

        md += "\n### Negative\n"
        for con in self.negative_consequences:
            md += f"- {con}\n"

        md += "\n### Risks\n"
        for risk in self.risks:
            md += f"- {risk}\n"

        md += "\n## Alternatives Considered\n"
        for alt in self.alternatives:
            md += f"\n### Alternative: {alt.name}\n"
            md += "**Pros:**\n"
            for pro in alt.pros:
                md += f"- {pro}\n"
            md += "\n**Cons:**\n"
            for con in alt.cons:
                md += f"- {con}\n"
            md += f"\n**Rejected because:** {alt.rejected_reason}\n"

        md += "\n## References\n"
        for ref in self.references:
            md += f"- {ref}\n"

        return md

# Ejemplo de uso
adr = ADR(
    number=5,
    title="Adopt TypeScript for new frontend code",
    status="Proposed",
    context="""
Our React codebase is 100% JavaScript. We've had recurring issues:
- 40% of production bugs are type-related (undefined is not a function)
- Refactoring is risky (no compile-time checks)
- New developers struggle to understand data shapes
- We spend ~2 hours/week debugging type issues
    """,
    decision="""
All new frontend code will be written in TypeScript starting March 1, 2024.

Scope:
- New components/modules: TypeScript required
- Existing code: Migrate gradually (no big-bang rewrite)
- Target: 80% TypeScript coverage by end of Q2
    """,
    positive_consequences=[
        "Catch bugs at compile-time instead of runtime",
        "Better IDE autocomplete and documentation",
        "Easier onboarding (types document the code)",
        "Safer refactoring with confidence"
    ],
    negative_consequences=[
        "Learning curve for team (2-3 weeks)",
        "Slower initial development (~20% slower for first month)",
        "Build times increase by ~30%",
        "Mixed JS/TS codebase during transition (6+ months)"
    ],
    risks=[
        "Team resistance to change",
        "Over-using 'any' defeats the purpose",
        "Strict types might slow down prototyping"
    ],
    alternatives=[
        Alternative(
            name="Flow (Facebook's type checker)",
            pros=[
                "Similar to TypeScript",
                "We already use React (also Facebook)"
            ],
            cons=[
                "Smaller community than TypeScript",
                "Facebook deprecated it internally",
                "Worse IDE support"
            ],
            rejected_reason="TypeScript has won the market. Flow is declining."
        ),
        Alternative(
            name="JSDoc comments for type hints",
            pros=[
                "Zero build step",
                "No migration needed",
                "Works with existing JS"
            ],
            cons=[
                "Not enforced (just hints)",
                "Verbose syntax",
                "No compile-time checks"
            ],
            rejected_reason="Doesn't solve the core problem: we need enforcement."
        ),
        Alternative(
            name="Keep JavaScript, add more tests",
            pros=[
                "No learning curve",
                "No migration",
                "Familiar tools"
            ],
            cons=[
                "Tests catch bugs later than types",
                "Test coverage never reaches 100%",
                "Doesn't help with refactoring"
            ],
            rejected_reason="Tests and types complement each other. Types prevent whole classes of bugs."
        )
    ],
    references=[
        "TypeScript Handbook: https://www.typescriptlang.org/docs/",
        "Internal: POC results in `experiments/typescript-migration`",
        "Survey: 8/10 engineers support TypeScript adoption"
    ]
)

print(adr.generate_markdown())

Receta 8.2: RFCs (Request for Comments)

¿Qué es? Documento de propuesta que invita feedback ANTES de implementar. Similar a ADR pero más temprano en el proceso (propuesta vs decisión).

ADR vs RFC:

Template de RFC:

# RFC-042: [Título de la propuesta]

**Author**: [Tu nombre]
**Created**: 2024-02-20
**Status**: Draft | In Review | Approved | Rejected
**Reviewers**: @tech-lead, @architect
**Target Decision Date**: 2024-03-01

## Summary
[1-2 párrafos explicando la propuesta en lenguaje simple]

## Motivation
¿Por qué estamos haciendo esto? ¿Qué problema resuelve?

### Problem Statement
[Descripción clara del problema actual]

### Goals
- Goal 1
- Goal 2

### Non-Goals
- Explícitamente NO vamos a hacer esto
- Explícitamente fuera de scope

## Proposed Solution

### Architecture Diagram
[Diagrama de la solución propuesta]

### Implementation Details
[Detalles técnicos de la implementación]

### API/Interface Changes
[Si aplica, mostrar cambios en APIs]

### Database Schema Changes
[Si aplica, mostrar cambios en schema]

### Migration Strategy
¿Cómo migramos del estado actual al nuevo estado?

## Alternatives Considered
[Similar a ADR, explicar alternativas]

## Trade-offs and Risks
- Trade-off 1
- Risk 1: [Descripción] | Mitigation: [Cómo mitigamos]

## Testing Strategy
¿Cómo validamos que funciona?

## Rollout Plan
1. Phase 1: ...
2. Phase 2: ...
3. Phase 3: ...

## Success Metrics
¿Cómo medimos éxito?
- Metric 1: Target value
- Metric 2: Target value

## Timeline
| Phase | Duration | Owner |
|-------|----------|-------|
| Design | 1 week | @alice |
| Implementation | 3 weeks | @bob |
| Testing | 1 week | @charlie |
| Rollout | 2 weeks | @alice |

## Open Questions
- [ ] Question 1 that needs answer?
- [ ] Question 2 we're not sure about?

## References
- Link 1
- Link 2

---

## Review Comments
[Area para que reviewers agreguen comments]

Ejemplo real de RFC:

# RFC-018: Implement Rate Limiting on API Gateway

**Author**: @sarah-backend
**Created**: 2024-02-20
**Status**: In Review
**Reviewers**: @tech-lead, @devops-lead, @security-lead
**Target Decision Date**: 2024-02-27

## Summary

Add rate limiting to our public API to prevent abuse and ensure fair usage.
Currently, we have no rate limits, which has led to:
- 3 incidents in Q4 2023 where single users overwhelmed the API
- $2,400 in unexpected cloud costs from abuse
- Degraded performance for legitimate users

Proposal: Implement tiered rate limiting based on user plan.

## Motivation

### Problem Statement

Our API currently has no rate limiting. Last month:
- User A made 10M requests in 1 day (normal is 50K)
- Caused p99 latency to spike to 5 seconds
- Cost us $800 in extra cloud compute
- Legitimate users complained about slow API

We need rate limiting to:
1. Prevent abuse
2. Control costs
3. Guarantee SLAs for paying customers
4. Create incentive for paid plans

### Goals
- Implement fair rate limiting per user/API key
- Different limits per pricing tier
- Graceful degradation (don't hard-fail)
- Observable (metrics + alerts)
- Zero downtime deployment

### Non-Goals
- NOT implementing GraphQL-specific rate limiting (only REST)
- NOT rate limiting internal services (only public API)
- NOT building custom rate limiter (use existing solution)

## Proposed Solution

### Architecture

    Client --> API Gateway (Rate Limit) --> Backend Services
                      |
                      v
                   Redis (Counters)

### Implementation Details

**Technology**: Use AWS API Gateway with Token Bucket algorithm

**Rate Limit Tiers**:
| Plan | Requests/min | Burst |
|------|--------------|-------|
| Free | 60 | 100 |
| Pro | 600 | 1000 |
| Enterprise | 6000 | 10000 |

**Response Headers**:
    X-RateLimit-Limit: 60
    X-RateLimit-Remaining: 45
    X-RateLimit-Reset: 1614556800

### Migration Strategy

**Phase 1: Soft Launch (Week 1)**
- Deploy rate limiting in "log-only" mode
- Collect data on who would be rate limited
- NO enforcement yet

**Phase 2: Warning Mode (Week 2)**
- Add X-RateLimit-* headers
- Send email warnings to users approaching limits
- Still no enforcement

**Phase 3: Enforcement (Week 3)**
- Enable enforcement for new users
- Grandfather existing free users at 2x limit for 1 month
- Send announcement email

**Phase 4: Full Rollout (Week 4)**
- Enforce limits for all users
- Monitor metrics

### Rollback Plan
Feature flag: RATE_LIMITING_ENABLED
- If issues, set flag to false
- Gradual rollout per user: 1% -> 10% -> 50% -> 100%

## Alternatives Considered

### Alternative 1: Build Custom Rate Limiter
**Pros:**
- Full control over algorithm
- No vendor lock-in

**Cons:**
- 3-4 weeks development time
- Need to maintain
- Reinventing the wheel

**Rejected**: AWS API Gateway rate limiting is proven and costs $0

### Alternative 2: Use Cloudflare Rate Limiting
**Pros:**
- More flexible than API Gateway
- Better DDoS protection

**Cons:**
- Adds another vendor ($200/month)
- Requires DNS change
- More complexity

**Rejected**: API Gateway sufficient for our needs

### Alternative 3: No Rate Limiting, Just Better Monitoring
**Pros:**
- Zero implementation effort

**Cons:**
- Doesn't solve abuse problem
- Doesn't prevent cost spikes
- Reactive instead of proactive

**Rejected**: Monitoring alone doesn't prevent abuse

## Trade-offs and Risks

**Trade-offs:**
- Simplicity vs Flexibility: Using API Gateway is simple but less flexible than custom solution
- UX vs Protection: Rate limiting hurts UX but protects system

**Risks:**
| Risk | Impact | Probability | Mitigation |
|------|--------|-------------|------------|
| Legitimate users get rate limited | High | Medium | Generous limits + burst allowance |
| Implementation bugs | Medium | Low | Gradual rollout + monitoring |
| Users churn due to limits | Medium | Low | Grandfather existing users |

## Testing Strategy

Load Testing:

```python
# Simulate 100 requests/second per user
import asyncio
import aiohttp

async def test_rate_limit():
    async with aiohttp.ClientSession() as session:
        tasks = []
        for i in range(200):  # Should hit 60/min limit
            tasks.append(session.get('https://api.example.com/v1/users'))

        responses = await asyncio.gather(*tasks)

        # Verify
        status_codes = [r.status for r in responses]
        assert status_codes.count(200) == 60
        assert status_codes.count(429) == 140

        # Check headers
        for r in responses[:60]:
            assert 'X-RateLimit-Limit' in r.headers

Rollout Plan

WeekActivityOwner
1Configure API Gateway usage plans@sarah-backend
1Deploy in log-only mode@devops-lead
2Add monitoring dashboards@devops-lead
2Email campaign: upcoming changes@product
3Enable for new users@sarah-backend
4Full rollout@sarah-backend

Success Metrics

Must-have:

Nice-to-have:

Open Questions

References


Review Comments

@tech-lead (2024-02-21):

Looks good overall. Question: What about burst traffic from legitimate users? E.g., user has cron job that makes 100 requests at midnight?

@sarah-backend (2024-02-21):

Good catch! That’s why we use Token Bucket with burst allowance. Free tier: 60/min but allows burst of 100. So cron job would work.

@security-lead (2024-02-22):

Approved. Suggest adding IP-based rate limiting too for DDoS protection.

@sarah-backend (2024-02-22):

Added to future work. Will do in Phase 2 (out of scope for this RFC).


---

## Receta 8.3: Technical Writing - Documentación Clara

**¿Qué es?**
Escribir documentación que otros desarrolladores puedan entender sin necesitar explicación adicional.

**Principios de good technical writing:**

```python
class TechnicalWritingPrinciples:
    """Principios para documentación clara"""

    @staticmethod
    def principle_1_know_your_audience():
        """Escribe para tu audiencia específica"""

        # PRINCIPLE 1: KNOW YOUR AUDIENCE
        # Different audiences need different detail levels:
        # - Para beginners: Start with WHY, not HOW. Use analogies y ejemplos.
        # - Para intermediate: Balance WHY and HOW. Link a conceptos.
        # - Para experts: Focus on edge cases, performance, trade-offs.
        pass

    @staticmethod
    def principle_2_structure():
        """Estructura predecible: What, Why, How, Troubleshooting"""
        # Every doc should follow:
        # 1. What is it? (1 sentence)
        # 2. Why do I care? (1 paragraph)
        # 3. How do I use it? (examples)
        # 4. How does it work? (details)
        # 5. What can go wrong? (troubleshooting)
        pass

    @staticmethod
    def principle_3_examples_first():
        """Ejemplos antes que teoría"""
        # Developers learn by doing. Show, don't tell.
        # - 1 example > 1000 words
        # - Show the HAPPY PATH first
        # - Then show edge cases
        # - Then explain HOW it works
        pass

    @staticmethod
    def principle_4_active_voice():
        """Voz activa, no pasiva"""
        # BAD (passive): "The configuration file should be updated."
        # GOOD (active): "Update the configuration file."
        #
        # BAD: "An error will be thrown if the input is invalid."
        # GOOD: "The function throws an error if the input is invalid."
        pass

    @staticmethod
    def principle_5_scannable():
        """Formato scannable: headers, bullets, code blocks"""
        # Developers scan, they don't read every word.
        # - Use headers (h2, h3) to create hierarchy
        # - Use bullet points for lists
        # - Use numbered lists for sequences
        # - Use code blocks for code
        # - Use **bold** for important terms
        # - Use tables for comparisons
        pass

Template de documentación de API:

# API Documentation Template

## Endpoint Name

### Quick Reference

    POST /api/v1/users

**Authentication Required**: Yes (Bearer token)

### What it does
Creates a new user account in the system.

### Request

**Headers:**

    Authorization: Bearer YOUR_API_KEY
    Content-Type: application/json

**Body:**
```json
{
  "email": "alice@example.com",
  "name": "Alice Smith",
  "role": "admin"
}

Parameters:

FieldTypeRequiredDescription
emailstringYesMust be valid email format
namestringYes2-50 characters
rolestringNoEither “user” or “admin” (default: “user”)

Response

Success (201 Created):

{
  "id": "usr_abc123",
  "email": "alice@example.com",
  "name": "Alice Smith",
  "role": "user",
  "created_at": "2024-02-20T10:30:00Z"
}

Error (400 Bad Request):

{
  "error": {
    "code": "INVALID_EMAIL",
    "message": "Email must be a valid format",
    "field": "email"
  }
}

Example

cURL:

curl -X POST https://api.example.com/v1/users \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "name": "Alice Smith"
  }'

Python:

import requests

response = requests.post(
    'https://api.example.com/v1/users',
    headers={'Authorization': 'Bearer sk_live_abc123'},
    json={
        'email': 'alice@example.com',
        'name': 'Alice Smith'
    }
)

user = response.json()
print(user['id'])  # usr_abc123

JavaScript:

const response = await fetch('https://api.example.com/v1/users', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_abc123',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    email: 'alice@example.com',
    name: 'Alice Smith'
  })
});

const user = await response.json();
console.log(user.id); // usr_abc123

Common Errors

StatusCodeReasonSolution
400INVALID_EMAILEmail format invalidUse valid email (name@domain.com)
400EMAIL_TAKENEmail already existsUse different email or update existing user
401UNAUTHORIZEDMissing/invalid API keyCheck Authorization header
429RATE_LIMITToo many requestsWait 60 seconds and retry

Rate Limits

Notes


---

## Receta 8.4: Presentaciones Técnicas

**¿Qué es?**
Presentar conceptos técnicos de forma clara a audiencias técnicas y no-técnicas.

**Framework: The Pyramid Principle**

```python
class PresentationStructure:
    """Estructura de presentaciones técnicas efectivas"""

    @staticmethod
    def pyramid_principle():
        """Start with conclusion, then support"""

        # Traditional (bottom-up):      Pyramid (top-down):
        # "Here's the data..."           "We should migrate to microservices"
        # "Here's the analysis..."       "Why? 3 reasons:"
        # "Therefore, we should..."      "1. Scalability..."
        #                                "2. Team autonomy..."
        #                                "3. Deployment speed..."
        #
        # Slide 1: CONCLUSION
        # Slide 2: WHY (3 key reasons)
        # Slides 3-5: EVIDENCE for each reason
        # Slides 6-7: HOW (implementation plan)
        # Slide 8: NEXT STEPS
        pass

    @staticmethod
    def technical_to_business():
        """Traducir tecnicismos a lenguaje de negocio"""

        translations = {
            "We need to refactor":
                "We need to reduce technical debt to ship features 40% faster",
            "Our CI/CD pipeline is broken":
                "Deployments take 3 hours instead of 30 minutes, slowing releases",
            "We should use Kubernetes":
                "This will reduce server costs by $3,000/month and eliminate downtime",
            "Database queries are slow":
                "Users wait 5 seconds for pages (target: <1 second)",
            "We have 40% test coverage":
                "60% of bugs reach production, costing 10 engineering hours/week",
            "Technical debt":
                "Code shortcuts that save time now but slow us down later (like credit card debt)"
        }

        # Formula: [Technical term] -> [Business impact]
        # Always include: Time saved/lost, Money saved/lost,
        #                 Customer impact, Competitive advantage, Risk reduction
        return translations

    @staticmethod
    def slide_design_rules():
        """Reglas de diseño de slides"""

        rules = [
            "Rule 1: ONE IDEA PER SLIDE",
            "Rule 2: 6x6 RULE - Max 6 bullets, max 6 words per bullet",
            "Rule 3: VISUALS > TEXT - Chart > bullet points describing trend",
            "Rule 4: HIGH CONTRAST - Black on white, or white on dark",
            "Rule 5: CONSISTENT FONT SIZE - Title 36-44pt, Body 24-32pt",
            "Rule 6: NO ANIMATIONS unless building complex diagram step-by-step"
        ]
        return rules

    @staticmethod
    def storytelling_framework():
        """Contar historias técnicas: SITUATION -> COMPLICATION -> RESOLUTION"""

        # SITUATION (Slide 1-2): Context y estado actual
        # COMPLICATION (Slide 3-4): El problema y su impacto real
        # RESOLUTION (Slide 5-8): Solución propuesta con ROI
        # CLOSE (Slide 9): Next steps claros
        #
        # Why stories work:
        # - Humans remember stories, not facts
        # - Emotional connection
        # - Clear problem -> solution arc
        # - Concrete examples > abstract concepts
        pass

Template de presentación técnica:

SLIDE DECK TEMPLATE
===================

Slide 1: TITLE
  [Project Name] | [Your name] | [Date]

Slide 2: TL;DR (Executive Summary)
  What: [One sentence]
  Why: [Business impact in numbers]
  Ask: [What you need from audience]
  Timeline: [When it happens]

Slide 3: THE PROBLEM
  [Describe current pain point]
  Impact:
  - Metric 1
  - Metric 2
  [Visual: chart/screenshot showing problem]

Slide 4-6: WHY NOW? (Evidence)
  - Charts, User feedback, Incident reports, Competitive analysis

Slide 7: PROPOSED SOLUTION
  [High-level description + Architecture diagram]
  Key benefits: Benefit 1 | Benefit 2 | Benefit 3

Slide 8: ALTERNATIVES CONSIDERED
  | Option | Pros | Cons | Cost |
  | A      |      |      |      |
  | B (✓)  |      |      |      |

Slide 9: IMPLEMENTATION PLAN
  Timeline: Week 1-2: Phase 1 | Week 3-4: Phase 2 | Week 5-6: Phase 3
  Resources: 2 engineers (6 weeks) | Budget: $X

Slide 10: RISKS & MITIGATION
  | Risk | Impact | Mitigation |

Slide 11: SUCCESS METRICS
  - Metric 1: Current -> Target
  - Metric 2: Current -> Target

Slide 12: NEXT STEPS
  1. [Action] - [Owner] - [Date]
  2. [Action] - [Owner] - [Date]
  Decision needed: [What you need from audience]

Slide 13: Q&A
  [Your email] | [Slack channel]

APPENDIX: Technical deep-dives, Additional data, Reference materials