Notification Hub API
Servicio de notificaciones multi-canal con procesamiento asíncrono
Microservicio backend para la gestión y entrega de notificaciones a través de múltiples canales: email (Resend), webhooks con firma HMAC-SHA256 y WebSocket en tiempo real. Los proyectos externos registran apps, reciben API keys y envían notificaciones que se procesan de forma asíncrona mediante BullMQ con reintentos automáticos, dead letter queue y rate limiting configurable por app.
1. Arquitectura
Routes (HTTP Layer)
Capa HTTP con Fastify v5 y validación JSON Schema. Define endpoints para CRUD de apps, envío de notificaciones, health check y WebSocket.
Services (Business Logic)
Lógica de negocio con acceso a datos via Drizzle ORM. Gestiona apps, notificaciones, generación de API keys y consultas con paginación offset y cursor.
Workers (Async Processing)
Procesamiento asíncrono con BullMQ (concurrency 10). Reintentos exponenciales (3 intentos), dead letter queue para jobs agotados y delivery a los tres canales.
2. Características
Core del Sistema
Registro de Apps
Las apps se registran con nombre y descripción. Cada una recibe una API key única (prefijo nh_ + 64 hex) mostrada solo una vez. Se almacena como hash SHA-256.
CRUD de Notificaciones
Envío individual o batch de notificaciones con canal, destinatario, body y metadata opcional. Consulta individual y listado con filtros (status, canal, rango de fechas) y paginación offset o cursor.
Seguimiento de Ciclo de Vida
Cada notificación se persiste con estados: pending → processing → delivered o failed. Conteo atómico por app con incremento SQL para evitar race conditions.
Rotación de API Keys
Endpoint admin para rotar la API key de cualquier app. La key anterior se invalida inmediatamente y se genera una nueva con el mismo formato.
Canales de Entrega
Email via Resend
Envío de emails HTML a través de la API de Resend usando fetch directo (sin SDK). El body de la notificación se envía como contenido HTML.
Webhooks con Firma HMAC
POST JSON al URL del destinatario con headers de verificación: X-Webhook-Timestamp y X-Webhook-Signature (HMAC-SHA256). El receptor puede validar autenticidad e integridad.
WebSocket en Tiempo Real
Push en tiempo real a clientes WebSocket conectados en /ws?recipient=ID&x-api-key=KEY. Si el destinatario está offline, el delivery falla inmediatamente.
Infraestructura
Rate Limiting por App
Límite configurable de notificaciones por minuto por app. Se aplica en el middleware de autenticación. Al exceder el límite, la app se bloquea temporalmente.
Cola de Jobs con BullMQ
Cola Redis-backed con workers concurrentes (10), reintentos exponenciales automáticos (3 intentos) y dead letter queue para jobs que agotan reintentos.
Observabilidad
Logging estructurado con Pino (debug en dev, info en prod). Health check que verifica conectividad a PostgreSQL y Redis simultáneamente.
Documentación Swagger
Documentación interactiva de la API auto-generada con @fastify/swagger y @fastify/swagger-ui, disponible en /docs con todos los endpoints.
3. Tech Stack
Drizzle
BullMQ 4. API Reference
| Módulo | Endpoints |
|---|---|
| Apps | 6 |
| Notifications | 4 |
| Health | 1 |
| WebSocket | 1 |
5. Decisiones de Diseño
API Key Hashing
Las API keys se generan con nh_ + 64 caracteres hex aleatorios. Se almacenan como hash SHA-256 en la DB. El plaintext se devuelve solo una vez en la creación. Esto limita el impacto si la DB se ve comprometida.
Procesamiento Asíncrono
Las notificaciones se insertan en una cola BullMQ-backed por Redis. El endpoint responde inmediatamente con status "pending". El worker procesa concurrentemente con reintentos automáticos y dead letter queue.
HMAC Webhook Signing
Los webhooks incluyen firma HMAC-SHA256 con timestamp. El receptor puede verificar que la notificación proviene del hub y que no fue alterada en tránsito, previniendo spoofing y replay attacks.
Dependency Injection para Testabilidad
El notification processor recibe todas sus dependencias (db, sendEmail, sendWebhook, sendWebSocket, deadLetterQueue) como parámetro. Esto permite testing unitario completo sin infraestructura.