Módulo 8: Proyecto Integrador — Deployed AI System

8. Proyecto Final: Deployed Production AI System

Descripción del proyecto

Este es el proyecto integrador de toda la guía — no solo del Módulo 8, sino de los 8 módulos completos. Vas a integrar todo lo que construiste y entregar dos artefactos: un sistema AI desplegado en producción real (con URL accesible desde internet) y documentación operativa profesional. No es un ejercicio — es el deployment de verdad. El resultado es el artefacto más portfolio-worthy de toda la guía.

Por qué importa: Este proyecto demuestra que no solo sabes deployar — sabes decidir cómo deployar, documentar tus decisiones, validar que funciona, y operar el sistema cuando algo falla. Es exactamente lo que un empleador quiere ver: un ingeniero que puede llevar un sistema de cero a producción con criterio profesional.


Objetivo del proyecto

Producir un Deployed Production AI System que incluya:

  1. Sistema AI desplegado en una plataforma real, accesible desde internet
  2. CI/CD pipeline que despliega automáticamente desde git push
  3. Health checks y smoke tests que validan la inferencia post-deploy
  4. Decision matrix v_final con justificación de estrategia y plataforma
  5. Runbook operativo con procedimientos para incidencias comunes
  6. Performance baseline con targets de latencia, costes, y error rate
  7. Deployment guide que otro ingeniero pueda seguir para replicar el setup

Recap del Módulo

Antes de empezar, asegúrate de tener los artefactos de cada cápsula:

CápsulaArtefactoLo usas para
02Diagrama de integraciónEntender cómo conectan las piezas
03GitHub Actions workflowAutomatizar test → build → deploy → validate
04Smoke test scriptValidar inferencia post-deploy
05Runbook templateDocumentar procedimientos de incidencia
06Decision matrix v_finalJustificar la estrategia y plataforma
07Performance baselineEstablecer métricas de referencia

Si te falta alguno, vuelve a la cápsula correspondiente y complétalo. El proyecto integra TODOS estos artefactos.


Especificaciones del Entregable

Entregable 1: Sistema Desplegado (50%)

REQUISITOS OBLIGATORIOS:
├── ✅ URL pública accesible desde cualquier navegador
│   Ejemplo: https://tu-app.railway.app
│
├── ✅ Health check endpoint
│   GET /health → {"status": "healthy", "version": "1.0.0"}
│
├── ✅ Readiness check con verificación de dependencias
│   GET /health/ready → {"status": "ready", "checks": {...}}
│
├── ✅ Endpoint de inferencia AI funcional
│   POST /api/inference → respuesta de LLM
│
├── ✅ CI/CD: git push a main → deploy automático
│   GitHub Actions workflow con test + build + deploy + validate
│
├── ✅ Variables de entorno configuradas (no hardcoded)
│   OPENAI_API_KEY, ENVIRONMENT, etc. en secrets de plataforma
│
└── ✅ Docker image funcional
    Dockerfile multi-stage, .dockerignore configurado

Entregable 2: Documentación Operativa (50%)

REQUISITOS OBLIGATORIOS:
├── ✅ Decision Matrix v_final (docs/decision-matrix.md)
│   Estrategia + plataforma + justificación + trade-offs
│
├── ✅ Runbook Operativo (docs/runbook.md)
│   Al menos 4 procedimientos con diagnóstico y resolución
│
├── ✅ Performance Baseline (docs/performance-baseline.md)
│   Latencia, costes, error rate, uptime con targets
│
├── ✅ Deployment Guide (docs/deployment-guide.md)
│   Instrucciones para replicar el setup desde cero
│
└── ✅ Post-deploy validation report
    Resultado de smoke tests contra producción

Caso de Estudio (si no tienes app AI propia)

DocuSearch AI — El mismo caso de toda la guía

Si no tienes tu propia app AI, usa el caso DocuSearch AI que has venido desarrollando. Aquí tienes el código mínimo necesario:

# src/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, field_validator
from openai import AsyncOpenAI
from src.config import get_settings
import time

app = FastAPI(title="DocuSearch AI", version="1.0.0")
settings = get_settings()
client = AsyncOpenAI(api_key=settings.openai_api_key)

class InferenceRequest(BaseModel):
    prompt: str

    @field_validator("prompt")
    @classmethod
    def prompt_not_empty(cls, v):
        if not v or not v.strip():
            raise ValueError("Prompt cannot be empty")
        return v.strip()

class InferenceResponse(BaseModel):
    response: str
    model: str
    latency_ms: int

@app.get("/health")
async def health():
    return {
        "status": "healthy",
        "version": "1.0.0",
        "environment": settings.environment,
    }

@app.get("/health/ready")
async def readiness():
    checks = {}
    try:
        await client.models.list()
        checks["openai"] = {"status": "connected"}
    except Exception as e:
        checks["openai"] = {"status": "error", "detail": str(e)[:100]}

    all_ok = all(c.get("status") == "connected" for c in checks.values())
    return {"status": "ready" if all_ok else "degraded", "checks": checks}

@app.post("/api/inference", response_model=InferenceResponse)
async def inference(request: InferenceRequest):
    start = time.time()
    try:
        completion = await client.chat.completions.create(
            model=settings.openai_model,
            messages=[
                {"role": "system", "content": "You are a helpful documentation assistant. Answer concisely."},
                {"role": "user", "content": request.prompt},
            ],
            max_tokens=500,
            temperature=0.7,
        )
        elapsed_ms = int((time.time() - start) * 1000)
        return InferenceResponse(
            response=completion.choices[0].message.content,
            model=settings.openai_model,
            latency_ms=elapsed_ms,
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Inference failed: {str(e)[:200]}")
# src/config.py
from pydantic_settings import BaseSettings
from functools import lru_cache

class Settings(BaseSettings):
    environment: str = "development"
    openai_api_key: str = ""
    openai_model: str = "gpt-4o-mini"
    debug: bool = False
    version: str = "1.0.0"

    class Config:
        env_file = ".env"

@lru_cache()
def get_settings() -> Settings:
    return Settings()
# Dockerfile
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
COPY src/ ./src/

FROM python:3.11-slim AS runtime
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app/src ./src/
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
# requirements.txt
fastapi>=0.109.0
uvicorn>=0.27.0
openai>=1.12.0
pydantic>=2.6.0
pydantic-settings>=2.1.0

Paso a Paso: El Deployment

Paso 1: Verificar que todo funciona localmente (15 min)

# Build Docker image
docker build -t docusearch-ai:latest .

# Run localmente
docker run -d --name local-test \
    -p 8000:8000 \
    -e OPENAI_API_KEY=$OPENAI_API_KEY \
    -e ENVIRONMENT=development \
    docusearch-ai:latest

# Verificar health
curl http://localhost:8000/health
# {"status":"healthy","version":"1.0.0","environment":"development"}

# Verificar readiness
curl http://localhost:8000/health/ready
# {"status":"ready","checks":{"openai":{"status":"connected"}}}

# Verificar inferencia
curl -X POST http://localhost:8000/api/inference \
    -H "Content-Type: application/json" \
    -d '{"prompt": "What is Docker?"}'
# {"response":"Docker is a platform for...","model":"gpt-4o-mini","latency_ms":1856}

# Cleanup
docker stop local-test && docker rm local-test

Si algo falla aquí, NO continúes. Arregla el problema local antes de intentar desplegar.

Paso 2: Configurar la plataforma (10-15 min)

Railway:

# Instalar CLI
npm install -g @railway/cli

# Login y crear proyecto
railway login
railway init

# Configurar variables de entorno
railway variables set OPENAI_API_KEY=sk-...
railway variables set ENVIRONMENT=production

# Deploy
railway up

Render:

1. render.com → New → Web Service
2. Connect GitHub repo
3. Settings:
   - Environment: Docker
   - Plan: Free
   - Health Check Path: /health
4. Environment Variables:
   - OPENAI_API_KEY: sk-...
   - ENVIRONMENT: production
5. Deploy

Fly.io:

# Instalar CLI
curl -L https://fly.io/install.sh | sh

# Login y crear app
fly auth login
fly launch --name docusearch-ai

# Configurar secrets
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set ENVIRONMENT=production

# Deploy
fly deploy

Paso 3: Verificar el deployment (5 min)

# Reemplaza con tu URL real
export PRODUCTION_URL="https://tu-app.railway.app"

# Health check
curl $PRODUCTION_URL/health

# Readiness
curl $PRODUCTION_URL/health/ready

# Inference
curl -X POST $PRODUCTION_URL/api/inference \
    -H "Content-Type: application/json" \
    -d '{"prompt": "What is deployment?"}'

# Smoke tests completos
python scripts/smoke_test.py $PRODUCTION_URL

Paso 4: Configurar CI/CD (15 min)

# .github/workflows/deploy.yml
name: Deploy AI System

on:
  push:
    branches: [main]
  workflow_dispatch:

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: 'pip'
      - run: pip install -r requirements.txt && pip install pytest httpx
      - run: pytest tests/ -v --tb=short
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          ENVIRONMENT: test

  deploy:
    if: github.ref == 'refs/heads/main'
    needs: test
    runs-on: ubuntu-latest
    timeout-minutes: 10
    environment: production
    steps:
      - uses: actions/checkout@v4
      # ADAPTA A TU PLATAFORMA:
      # Railway:
      - run: npm install -g @railway/cli
      - run: railway up --detach --service ${{ vars.RAILWAY_SERVICE_ID }}
        env:
          RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}

  validate:
    needs: deploy
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Wait for deployment
        run: sleep 60
      - name: Run smoke tests
        run: python scripts/smoke_test.py "${{ vars.PRODUCTION_URL }}"

Configura en GitHub:

  • Secrets: OPENAI_API_KEY, RAILWAY_TOKEN (o el de tu plataforma)
  • Variables: PRODUCTION_URL, RAILWAY_SERVICE_ID

Paso 5: Verificar CI/CD end-to-end (10 min)

# Haz un cambio menor y push
echo "# Updated $(date)" >> README.md
git add -A
git commit -m "test: verify CI/CD pipeline"
git push origin main

# Ve a GitHub → Actions → observa el pipeline
# Debe pasar: test ✅ → deploy ✅ → validate ✅

Paso 6: Configurar monitoreo (5 min)

UptimeRobot:
1. New Monitor → HTTP(s)
2. URL: https://tu-app.railway.app/health
3. Interval: 5 minutes
4. Alert contacts: tu email

Paso 7: Crear documentación (30-45 min)

Crea los 4 documentos en la carpeta docs/:

docs/decision-matrix.md — Tu decision matrix v_final (cápsula 06) docs/runbook.md — Tu runbook operativo (cápsula 05) docs/performance-baseline.md — Tus baselines de performance (cápsula 07) docs/deployment-guide.md — Ver template abajo


Template: Deployment Guide

# Deployment Guide — [Nombre del Sistema]

## Prerequisites
- Docker 24.0+
- Python 3.11+
- GitHub account
- [Tu plataforma] account
- OpenAI API key

## Step 1: Clone and Setup
git clone https://github.com/[tu-user]/[tu-repo].git
cd [tu-repo]
cp .env.example .env
# Edit .env with your API keys

## Step 2: Run Locally
docker build -t [app-name]:latest .
docker run -d --name local \
    -p 8000:8000 \
    --env-file .env \
    [app-name]:latest
curl http://localhost:8000/health

## Step 3: Deploy to [Platform]
[Platform-specific steps]

## Step 4: Configure CI/CD
1. Add secrets to GitHub: [list]
2. Add variables to GitHub: [list]
3. Push to main to trigger deploy

## Step 5: Verify
python scripts/smoke_test.py [production-url]

## Step 6: Monitor
- UptimeRobot: [URL]
- OpenAI Usage: platform.openai.com

## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| OPENAI_API_KEY | Yes | OpenAI API key |
| ENVIRONMENT | Yes | development/staging/production |
| [Others] | ... | ... |

## Troubleshooting
- [Common issue 1]: [Solution]
- [Common issue 2]: [Solution]

Estructura Final del Proyecto

tu-proyecto-ai/
├── .github/
│   └── workflows/
│       ├── deploy.yml              # CI/CD pipeline
│       └── rollback.yml            # Rollback workflow (opcional)
├── src/
│   ├── __init__.py
│   ├── main.py                     # FastAPI app
│   └── config.py                   # Settings con Pydantic
├── tests/
│   ├── __init__.py
│   └── test_health.py              # Tests básicos
├── scripts/
│   ├── smoke_test.py               # Smoke tests
│   ├── validate-deploy.sh          # Validación bash
│   ├── measure_latency.py          # Medición de latencia
│   └── verify_secrets.py           # Verificación de env vars
├── docs/
│   ├── decision-matrix.md          # Decision matrix v_final
│   ├── runbook.md                  # Runbook operativo
│   ├── performance-baseline.md     # Baselines de performance
│   └── deployment-guide.md         # Guía de deployment
├── Dockerfile                      # Multi-stage build
├── .dockerignore                   # Exclusiones del image
├── docker-compose.yml              # Desarrollo local
├── requirements.txt                # Dependencias Python
├── .env.example                    # Template de env vars
└── README.md                       # Overview del proyecto

Checklist de Completitud

Sistema Desplegado

  • URL pública accesible: https://____________
  • GET /health retorna 200 con status "healthy"
  • GET /health/ready verifica dependencias (OpenAI)
  • POST /api/inference procesa un prompt y retorna respuesta del LLM
  • Variables de entorno configuradas en la plataforma (no hardcoded)
  • Docker image funciona localmente con docker build + docker run

CI/CD Pipeline

  • git push main dispara el pipeline automáticamente
  • Job test ejecuta pytest con éxito
  • Job deploy despliega a la plataforma elegida
  • Job validate ejecuta smoke tests contra producción
  • Pipeline completo en < 10 minutos
  • Secrets configurados en GitHub (API keys, platform tokens)

Documentación

  • docs/decision-matrix.md con criterios ponderados, evaluación, y justificación
  • docs/runbook.md con al menos 4 procedimientos de incidencia
  • docs/performance-baseline.md con latencia, costes, error rate, uptime targets
  • docs/deployment-guide.md que otro ingeniero puede seguir desde cero
  • Smoke test script funcional (scripts/smoke_test.py)
  • README.md actualizado con overview del proyecto

Monitoreo

  • UptimeRobot (o alternativa) configurado con health check cada 5 min
  • Alertas de downtime configuradas (email o Slack)
  • Spending alerts en OpenAI configuradas

Calidad

  • El sistema funciona después de 24+ horas sin intervención
  • Un git push con cambio menor dispara deploy exitoso
  • Los smoke tests pasan consistentemente (>95% success rate)
  • La documentación es autosuficiente (alguien externo la entiende)
  • El runbook fue probado con al menos una incidencia simulada

Criterios de Evaluación

Rúbrica

CriterioPesoExcelente (5)Bueno (3)Insuficiente (1)
Deploy funcional25%URL pública, health checks, inferencia funcionalURL funcional pero falta algún checkNo desplegado o no accesible
CI/CD20%Pipeline completo con validatePipeline con test y deploySin CI/CD o manual
Decision matrix15%v_final con datos reales y validationMatrix con criterios pero sin datos realesMatrix incompleta o genérica
Runbook15%4+ procedimientos probados3 procedimientos básicos<3 procedimientos o no probados
Performance baseline10%4 métricas con targets y alertas2-3 métricas documentadasSin baselines o sin targets
Deployment guide10%Otro ingeniero replica el setupInstrucciones parcialesSin guía o incompleta
Monitoreo5%UptimeRobot + alertas configuradasMonitoreo básicoSin monitoreo

Niveles de entrega

NIVEL BÁSICO (aprueba):
├── Sistema desplegado con URL funcional
├── Health check que responde 200
├── Inferencia que funciona
├── Decision matrix con justificación
└── CI/CD con al menos test + deploy

NIVEL AVANZADO (destacado):
├── Todo lo básico +
├── Smoke tests automatizados post-deploy
├── Runbook con 4+ procedimientos probados
├── Performance baseline con 4 métricas
├── Deployment guide completa
├── Monitoreo externo configurado
└── Rollback strategy documentada y probada

NIVEL EXCEPCIONAL (portfolio-worthy):
├── Todo lo avanzado +
├── Pipeline con staging → production
├── Post-mortem de incidencia simulada
├── Sensitivity analysis en decision matrix
├── Caching implementado para responses frecuentes
└── Documentación que parece de un equipo profesional

Verificación Final: Script de Validación Completa

Script all-in-one para verificar el proyecto

# scripts/verify_project.py
"""
Verificación completa del proyecto final.
Ejecutar: python scripts/verify_project.py https://tu-app.railway.app
"""
import sys
import os
import json
import time
import urllib.request
import urllib.error

def check(name: str, condition: bool, detail: str = ""):
    icon = "PASS" if condition else "FAIL"
    msg = f"  [{icon}] {name}"
    if detail:
        msg += f" — {detail}"
    print(msg)
    return condition

def verify_deployment(base_url: str) -> dict:
    """Verifica todos los requisitos del sistema desplegado."""
    results = {"passed": 0, "failed": 0, "tests": []}

    print(f"\n{'='*60}")
    print(f"PROJECT VERIFICATION: {base_url}")
    print(f"{'='*60}")

    # 1. Health check
    print("\n--- System Health ---")
    try:
        req = urllib.request.Request(f"{base_url}/health")
        resp = urllib.request.urlopen(req, timeout=15)
        data = json.loads(resp.read())
        ok = check("Health endpoint", resp.status == 200, f"status={data.get('status')}")
        ok2 = check("Version present", "version" in data, f"v={data.get('version')}")
    except Exception as e:
        ok = check("Health endpoint", False, str(e)[:80])
        ok2 = False

    # 2. Readiness check
    try:
        req = urllib.request.Request(f"{base_url}/health/ready")
        resp = urllib.request.urlopen(req, timeout=15)
        data = json.loads(resp.read())
        ok3 = check("Readiness endpoint", resp.status == 200, f"status={data.get('status')}")
        ok4 = check("Dependency checks", "checks" in data, f"checks={list(data.get('checks',{}).keys())}")
    except Exception as e:
        ok3 = check("Readiness endpoint", False, str(e)[:80])
        ok4 = False

    # 3. Inference
    print("\n--- AI Inference ---")
    try:
        payload = json.dumps({"prompt": "What is 2+2? Answer briefly."}).encode()
        req = urllib.request.Request(
            f"{base_url}/api/inference",
            data=payload,
            headers={"Content-Type": "application/json"},
        )
        start = time.time()
        resp = urllib.request.urlopen(req, timeout=30)
        latency = (time.time() - start) * 1000
        data = json.loads(resp.read())
        ok5 = check("Inference endpoint", resp.status == 200, f"{latency:.0f}ms")
        ok6 = check("Response has content", len(data.get("response", "")) > 0)
        ok7 = check("Latency < 10s", latency < 10000, f"{latency:.0f}ms")
    except Exception as e:
        ok5 = check("Inference endpoint", False, str(e)[:80])
        ok6 = ok7 = False

    # 4. Error handling
    print("\n--- Error Handling ---")
    try:
        payload = json.dumps({"prompt": ""}).encode()
        req = urllib.request.Request(
            f"{base_url}/api/inference",
            data=payload,
            headers={"Content-Type": "application/json"},
        )
        resp = urllib.request.urlopen(req, timeout=10)
        ok8 = check("Empty prompt rejected", False, f"Expected 422, got {resp.status}")
    except urllib.error.HTTPError as e:
        ok8 = check("Empty prompt rejected", e.code == 422, f"status={e.code}")
    except Exception as e:
        ok8 = check("Empty prompt rejected", False, str(e)[:80])

    # 5. Documentation files
    print("\n--- Documentation ---")
    doc_files = [
        "docs/decision-matrix.md",
        "docs/runbook.md",
        "docs/performance-baseline.md",
        "docs/deployment-guide.md",
    ]
    for doc in doc_files:
        exists = os.path.exists(doc)
        check(f"File: {doc}", exists)

    # 6. CI/CD
    print("\n--- CI/CD ---")
    ci_file = ".github/workflows/deploy.yml"
    check(f"File: {ci_file}", os.path.exists(ci_file))

    # 7. Scripts
    print("\n--- Scripts ---")
    scripts = ["scripts/smoke_test.py"]
    for script in scripts:
        check(f"File: {script}", os.path.exists(script))

    print(f"\n{'='*60}")
    print("Verification complete.")
    print(f"{'='*60}\n")

if __name__ == "__main__":
    url = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8000"
    verify_deployment(url)

Ejecución

# Verificar todo de una vez
python scripts/verify_project.py https://tu-app.railway.app

# Output esperado:
# ============================================================
# PROJECT VERIFICATION: https://tu-app.railway.app
# ============================================================
#
# --- System Health ---
#   [PASS] Health endpoint — status=healthy
#   [PASS] Version present — v=1.0.0
#   [PASS] Readiness endpoint — status=ready
#   [PASS] Dependency checks — checks=['openai']
#
# --- AI Inference ---
#   [PASS] Inference endpoint — 2340ms
#   [PASS] Response has content
#   [PASS] Latency < 10s — 2340ms
#
# --- Error Handling ---
#   [PASS] Empty prompt rejected — status=422
#
# --- Documentation ---
#   [PASS] File: docs/decision-matrix.md
#   [PASS] File: docs/runbook.md
#   [PASS] File: docs/performance-baseline.md
#   [PASS] File: docs/deployment-guide.md
#
# --- CI/CD ---
#   [PASS] File: .github/workflows/deploy.yml
#
# --- Scripts ---
#   [PASS] File: scripts/smoke_test.py
#
# ============================================================
# Verification complete.
# ============================================================

Troubleshooting del Proyecto

"No puedo desplegar porque mi app necesita un servicio adicional (Redis, DB)"

Solución: Para el proyecto, simplifica la arquitectura. Usa solo FastAPI + OpenAI API (sin Redis ni DB). La complejidad está en la integración del deployment, no en la app. Si insistes en DB, Railway y Render permiten agregar servicios adicionales (PostgreSQL, Redis) desde el dashboard.

"El deploy funciona pero la validación falla intermitentemente"

Solución:

# Incrementar tiempos de espera y retries
- name: Wait for deployment
  run: sleep 90  # Dar más tiempo, especialmente en free tier

# Agregar retry al smoke test
- name: Run smoke tests with retry
  run: |
    for i in 1 2 3; do
      python scripts/smoke_test.py "$URL" && exit 0
      echo "Attempt $i failed, retrying in 30s..."
      sleep 30
    done
    exit 1

"Mi API key de OpenAI no funciona en producción pero sí local"

Solución:

# Verificar que la key está configurada correctamente en la plataforma
# No debería tener espacios, saltos de línea, ni comillas

# Railway
railway variables | grep OPENAI

# Fly.io
fly secrets list

# Test directo de la key
curl https://api.openai.com/v1/models \
    -H "Authorization: Bearer sk-tu-key-aqui" | head -c 100

"El pipeline tarda demasiado y a veces hace timeout"

Solución: Optimiza el pipeline:

# Usar cache de pip
- uses: actions/setup-python@v5
  with:
    cache: 'pip'

# Paralelizar test y build si son independientes
# Reducir número de tests en CI (solo critical path)
# Usar timeout-minutes en cada job

"¿Cómo hago el proyecto sin gastar dinero?"

Solución: Todas las plataformas recomendadas tienen free tier:

Railway: $5 crédito/mes gratis (más que suficiente para un proyecto)
Render: 750 horas/mes de instancias gratis
Fly.io: 3 VMs compartidas gratis
AWS Lambda: 1M requests/mes gratis

OpenAI: Usa gpt-4o-mini ($0.15/1M input tokens) — 
        500 requests/día × 30 días = 15K requests/mes ≈ $1.35/mes

Resultado Final

Al completar este proyecto tendrás:

✅ SISTEMA DESPLEGADO
   URL: https://tu-app.railway.app (o tu plataforma)
   Health: /health → healthy
   Inference: /api/inference → respuesta del LLM
   CI/CD: git push → deploy automático

✅ DOCUMENTACIÓN PROFESIONAL
   Decision matrix: justificación con datos reales
   Runbook: 4+ procedimientos de incidencia
   Baselines: latencia, costes, error rate, uptime
   Deploy guide: instrucciones replicables

✅ MONITOREO
   UptimeRobot: health check cada 5 min
   Alertas: email si el servicio cae
   Cost alerts: OpenAI spending limits

Portfolio value

Este proyecto demuestra:

  • Criterio de decisión: Decision matrix con trade-offs documentados
  • Ejecución técnica: Docker + CI/CD + deployment + validation
  • Mentalidad de producción: Runbook, baselines, monitoreo
  • Comunicación: Documentación que otro ingeniero puede usar

Es el artefacto más completo que puedes mostrar en una entrevista de infraestructura o AI engineering.


Conexión con la Guía

¿Qué sigue?

Con tu sistema AI desplegado en producción:

Guía #18 — Monitoring & Observability for AI: Tu sistema está en producción. Ahora necesitas ver qué pasa dentro de él: métricas de inferencia, logs estructurados, tracing distribuido, alertas inteligentes, y dashboards. La transición es natural: "Tienes un sistema AI en producción → ahora necesitas observarlo."

Lo que llevas de esta guía a la #18:

  • Un sistema AI funcional en producción (este proyecto)
  • Performance baselines (cápsula 07)
  • Health checks y smoke tests (cápsula 04)
  • Runbook para incidencias (cápsula 05)

Lo que la guía #18 agrega:

  • Structured logging con contexto de inferencia
  • Métricas custom (token usage, latencia por modelo, cache hit rate)
  • Distributed tracing (request → preprocessing → LLM → postprocessing)
  • Alertas basadas en anomalías (no solo thresholds estáticos)
  • Dashboards para stakeholders técnicos y no-técnicos

Nota Final

Acabas de poner tu primer sistema AI en producción — esto es real.

No es un tutorial que termina con "y así se deployaría." Es una URL real que cualquier persona con internet puede acceder. Es un pipeline que despliega automáticamente cuando haces push. Es documentación que otro ingeniero puede seguir para operar el sistema.

Esto es lo que separa a un developer que experimenta de uno que entrega en producción. La experiencia de ver tu sistema AI respondiendo en internet, con documentación profesional, monitoreo configurado, y procedimientos de incidencia listos — esa experiencia no la da ningún tutorial.

Lo que construiste aquí es la base de todo lo que viene: monitoring, observability, scaling, multi-region. Pero lo más importante es que ya tienes algo en producción. Y eso cambia todo.


Resumen

  • Desplegaste un sistema AI en producción con URL pública accesible, health check y endpoint de inferencia funcional.
  • Configuraste un pipeline CI/CD (GitHub Actions) que despliega automáticamente desde git push a main.
  • Implementaste health checks y readiness checks que validan dependencias (OpenAI) post-deploy.
  • Documentaste la decisión con una decision matrix v_final con justificación de estrategia y plataforma.
  • Creaste un runbook operativo con procedimientos concretos para incidencias comunes.
  • Definiste un performance baseline con targets de latencia, costes, error rate y uptime.

Recursos para el Proyecto

  1. Architecture Decision Records — Formato para documentar decisiones
  2. The Twelve-Factor App — Principios de apps production-ready
  3. Google SRE Book — Referencia de operaciones en producción
  4. Render Documentation — Docs para deployment en Render
  5. Railway Documentation — Docs para deployment en Railway
  6. Fly.io Documentation — Docs para deployment en Fly.io
  7. GitHub Actions Documentation — CI/CD con GitHub Actions
  8. UptimeRobot — Monitoreo de uptime gratuito
  9. OpenAI API Reference — Referencia de la API de OpenAI
  10. FastAPI Deployment — Documentación oficial de deployment de FastAPI