# ADR-002: Almacenamiento de Avatares ## Estado Aceptado ## Fecha 2026-05-06 ## Contexto Los usuarios pueden subir avatares personalizados. Necesitamos decidir dónde y cómo almacenar las imágenes de perfil para optimizar costo, rendimiento y mantenimiento. ## Decisión Usar **Storage Service externo (S3-compatible)** con URLs firmadas para avatares. ## Justificación 1. **Simplicidad**: No requerimos procesar imágenes en nuestro servidor 2. **Costo**: S3-like storage es económico ($0.023/GB) 3. **CDN**: Los avatares se sirven desde CDN automáticamente 4. **Seguridad**: URLs firmadas con expiración evitan hotlinking 5. **Mantenimiento**: No requiere gestión de sistema de archivos ## Consecuencias ### ✅ Positivas - No hay infraestructura de archivos que mantener - Escalabilidad automática - URLs firmadas = más seguridad - Cache CDN = mejor performance ### ❌ Negativas - Dependencia de proveedor externo - Costo de storage + egress - Latencia extra por redirect a CDN ### 🔄 Neutrales - Requiere configuración de CORS ## Alternativas Consideradas ### Opción A: Almacenamiento local en servidor - **Pros**: Sin dependencia externa, rápido para lecturas - **Contras**: No escala horizontalmente, requiere backup, problemas de disco - **Razón de descarte**: No escala bien con múltiples instancias ### Opción B: Base de datos como BLOB - **Pros**: Todo en un lugar, transacciones integradas - **Contras**: PostgreSQL no optimizado para archivos grandes, backup lento - **Razón de descarte**: degrada performance de DB, backups muy pesados ### Opción C: Servicio dedicado de imágenes (Cloudinary/Imgix) - **Pros**: Transformación de imágenes, CDN incluido, optimización automática - **Contras**: Más costoso ($50+/mes), vendor lock-in - **Razón de descarte**: Over-engineering para avatares simples ## Implementación 1. Cliente sube imagen a `/api/v1/profile/upload` (multipart) 2. Servicio valida tipo (jpg/png/webp) y tamaño (<5MB) 3. Servicio sube a S3 con nombre `avatars/{user_id}/{timestamp}.{ext}` 4. Servicio genera URL firmada (7 días validez) 5. URL se guarda en campo `avatar_url` del perfil ## Notas - Considerar WebP en el futuro para optimización - Implementar cleanup de avatares huérfanos (job semanal) ## Relacionado con - Feature F-002 - Componente: UserProfileService