Proyecto destacado · Product Engineering · Full Stack
Proyecto portfolio de full-stack. Construí un MES (Manufacturing Execution System) que resuelve el problema que viví durante 8 años como operario en el sector industrial: escritura transaccional offline (IndexedDB + outbox), multi-tenant con aislamiento a nivel de base de datos (PostgreSQL RLS), sincronización durable con BullMQ y una interfaz pensada para manos con guantes.
Tecnologías: TypeScript, NestJS, React, PostgreSQL 16 + Prisma, Redis + BullMQ, Dexie.js, Docker/K8s, GitHub Actions. Ver arquitectura completa →
Pasé mis últimos 8 años como operario de fábrica en el sector industrial. Vi cómo el trabajo real -turnos, máquinas CNC, operarios con guantes, ruido y WiFi que cae- chocaba cada día con herramientas diseñadas en oficinas con conexión estable y ratón.
Registros en papel por manos manchadas de grasa o aceite, con letra ilegible. Cada operario pierde una media de 5 minutos al día para después traspasarlo a Excel. El jefe de equipo no tiene control real de lo producido sin pasearse por cada puesto. Los relevos no se comunican entre sí. Y los ERPs generalistas son complejos para el operario y obsoletos para la planta.
Kavana Manufacturing no nació de un ejercicio de programación. Nació de la desconexión que yo mismo viví entre lo planificado y la experiencia real en el suelo de la fábrica. Mi cabeza empezó a detectar patrones y medidas para hacer el trabajo mucho más sencillo al operario y a oficina: si algo se puede hacer en dos clics en lugar de cinco, eso ya es una mejora sustancial. Este proyecto demuestra cómo traduje esa experiencia en arquitectura.
NestJS con 17 módulos (orders, OEE, quality, costs, sync, auth, tenants...) y guards globales: auth, contexto de tenant, rate-limit, validación. API OpenAPI 3.1.
Shared schema + Row Level Security en PostgreSQL. El aislamiento lo enforza la base de datos (client_id), imposible de evadir incluso con SQL raw. Verificado con tests cross-tenant. ADR →
Dexie.js/IndexedDB como base de datos local completa, no un Service Worker que solo cachea assets. El operario crea órdenes y registra calidad sin red; cada mutación genera un evento en cola local (outbox). ADR →
Colas Redis (sync:push, sync:pull, analytics:aggregate) con retry exponencial, dead-letter e idempotency keys. Nada se pierde aunque el cliente esté días offline. Métricas Prometheus por cola.
Unitarios, integración y e2e con Testcontainers (PostgreSQL y Redis reales en CI). Incluye tests de aislamiento multi-tenant, cálculos OEE y transacciones atómicas de stock.
Botones de 64px, contraste alto, flujo lineal. Diseñada para pantallas táctiles industriales y manos con guantes, no para ratón de oficina. Si el control es pequeño, el operario falla y deja de registrar. ADR →
Soft deletes, optimistic locking y transacciones atómicas multi-paso. Índices compuestos para las queries de planta. La BD es la única fuente de verdad del aislamiento.
Disponibilidad, rendimiento y calidad calculados por línea y turno en planta, no estimados en papel. Material + mano de obra + energía registrados por orden en origen.
Docker multi-stage (builder → distroless, non-root) + manifiestos K8s (Deployment, HPA, Ingress) + GitHub Actions: lint → typecheck → test → build → push.
Cada decisión clave con contexto, alternativas evaluadas y consecuencias: RLS, feature flags, offline-first, UX, toolings. Ver ADRs →
Más allá de las tecnologías, aquí hay decisiones de arquitectura que nacen del producto, no de la tecnología. Cada una responde a un requisito real de planta y tiene su ADR.
Un solo esquema = migraciones únicas, pooling eficiente, simplicidad operativa. El aislamiento se enforza a nivel de fila con current_setting('app.current_tenant'). Trade-off: disciplina en middleware y tests de aislamiento obligatorios. ADR →
El Service Worker cachea assets pero no resuelve la escritura transaccional offline. Con Dexie + outbox el operario sigue trabajando sin red y la UI nunca bloquea por red. Trade-off: complejidad de sincronización e idempotency keys. ADR →
Poca información por pantalla, 64px mínimo, contraste alto. La interfaz se diseñó para el operario con guantes en una pantalla industrial: si algo se puede hacer en dos clics en lugar de cinco, eso ya es una mejora sustancial. ADR →
El polling gasta batería y red. La cola durable garantiza que ninguna mutación se pierde aunque el cliente esté offline días. Retry exponencial, dead-letter y observabilidad real por cola.
Si no testeas el aislamiento multi-tenant, no tienes multi-tenant. 233 tests (216 backend + 17 frontend) verifican comportamiento: aislamiento cross-tenant, cálculos OEE, sync offline, auth flows. Con Testcontainers, la CI usa PostgreSQL y Redis reales.
En 6 meses no recordarás por qué elegiste RLS sobre schema-per-tenant. Los 5 ADRs y el DECISIONS.md convierten decisiones tribales en conocimiento transferible. Es como trabajan los equipos de ingeniería maduros. Ver ADRs →
Transparencia total: cada punto se puede verificar en el repositorio público. No hay clientes en producción.
El proyecto está vivo. Cada semana avanzo en los módulos planificados. El repo refleja el estado real en cada commit.
Frontend en Vercel, backend en Render, PostgreSQL en Neon. Demo pública desplegada.
Abrir demo →Repositorio público con docker-compose: levanta PostgreSQL, Redis, backend y frontend en local con un comando.
Ver en GitHub →Este es uno de los proyectos de mi portfolio. Si quieres ver el código, las decisiones técnicas documentadas, o simplemente conectar: