commit&push

~/blog $ git show 2025-10-11

Overengineering: ¿visión de futuro, ego, o solo una forma de aprender?

· 5 min de lectura · Victor Benavides

Lo admito: sobre-ingenierié uno de mis proyectos a sabiendas.

Se suponía que era un prototipo pequeño, del tipo que levantarías como monolito y mantendrías simple hasta probar que tenía usuarios. En lugar de eso, me fui por el otro lado. Diseñé una arquitectura de microservicios completa: veinticinco servicios en total, cada uno con su propio alcance, corriendo en contenedores con sidecars, y hablándose a través de un API Gateway impulsado por Dapr. Alguien podría ver eso y decir: "¿por qué demonios construirías microservicios para algo que quizá ni siquiera sobreviva al lanzamiento?"

¿La respuesta honesta?

  • Porque era mi proyecto, y podía.
  • Porque quería ver qué tan lejos podía empujar la arquitectura.
  • Y porque sabía que incluso si era "demasiado" para el día uno, el ejercicio me enseñaría cosas que llevaría conmigo a cada proyecto de ahí en adelante.

Construí submódulos que después evolucionarían en paquetes reutilizables: contratos de protobuf, entidades compartidas, infraestructura y DTOs. Realmente no necesitaba gRPC para este proyecto, pero como ya estaba sobre-ingenieriando, decidí irme con todo. Si íbamos a cometer errores, mejor cometerlos a escala.

El diseño llegó incluso a separar las operaciones CRUD en microservicios independientes — uno para Create, uno para Read, uno para Update y uno para Delete. Suena ridículo en el papel, pero el enfoque se convirtió en una plantilla repetible. Después de pasar tres semanas construyendo los primeros cuatro servicios, el resto empezó a fluir rápido. Solo tenía que cambiar nombres, entidades y DTOs, y los microservicios se volvieron casi de molde.

Por supuesto, hay trade-offs. Correr veinticinco servicios en contenedores con sidecars es caro, y los costos de deployment se van directo al cielo si el proyecto crece. Un monolito habría sido más simple y más barato en el corto plazo. Pero lo que gané fue invaluable: experiencia estructurando microservicios, diseñando módulos reutilizables y construyendo patrones escalables. Si TuJuerga algún día despega, la base está ahí para escalar multi-tenant. Y aunque no despegue, ahora tengo lecciones prácticas sobre overengineering, sobre cómo se ve el future-proofing de verdad, y sobre cómo balancear legibilidad, reusabilidad y mantenibilidad.

Por qué sobre-ingenieriamos

Si soy honesto, mucho del overengineering se reduce al ego. Los desarrolladores queremos mostrar lo que podemos hacer, demostrarle al equipo que somos la persona a la que los demás deberían acudir por consejos, patrones o ideas. El overengineering se convierte en una forma de decir: "mira la arquitectura que construí — esto no es solo una app simple, esto es un sistema." Aunque no siempre es solo ego. A veces es ambición, a veces es curiosidad. Pero en el fondo, siempre hay un poco de orgullo en construir algo más grande de lo necesario, solo para demostrar que podemos.

Los costos

Los costos del overengineering son reales. La complejidad sube rápido. Lo que podría tomar un solo día en un diseño directo puede inflarse a dos semanas de exploración, experimentación e implementación. Las tecnologías y patrones nuevos hacen la curva de aprendizaje aún más empinada. Eventualmente, el ritmo se acelera. Una vez que los primeros servicios están listos, el resto se vuelve más fácil. Pero la inversión inicial es enorme, y para un proyecto que quizá nunca necesite ese nivel de complejidad, es difícil de justificar.

Los beneficios

Para mí, el beneficio más grande es la libertad. Puedo explorar tecnologías y patrones que quizá nunca tocaría con un cronograma apretado en el trabajo. Este proyecto bebé fue mi patio de juegos para experimentar con gRPC, Dapr y diseño de microservicios a una escala que habría sido impensable en un ambiente corporativo. Y sí, el ego también juega su papel aquí. Puedo llevar lo que aprendí de vuelta al trabajo y decir: "ya hice esto antes. Sé cómo funciona." El overengineering se volvió una forma de subir de nivel, aunque el proyecto en sí no lo exigiera.

Estancamiento y pasión

Hay otra razón por la que sobre-ingenieriamos: el miedo al estancamiento.

En nuestros trabajos es fácil quedarse atorado en la repetición — arreglando los mismos bugs, desplegando los mismos patrones, viviendo en la rueda de hámster corporativa donde cada sprint se siente como una repetición del anterior. Empiezas a preocuparte por tu relevancia. ¿Estás creciendo? ¿Te estás manteniendo al día? ¿O te estás deslizando lentamente hacia quedar desactualizado? Por eso los proyectos bebé se convierten en un lienzo para el overengineering. Son donde peleamos contra la monotonía. Le echamos cada herramienta, cada patrón, cada tecnología nueva a la mezcla, aunque sea frustrante y desordenado. Lo hacemos porque amamos esta profesión.

Para mí, siempre regresa a la misma sensación que tuve a los ocho años, viendo mi primer clon de Space Invaders cobrar vida en una Commodore 64. Ese momento de asombro, de ver una pantalla responder a algo que yo había construido — rápido, sin errores, haciendo exactamente lo que le pedía — nunca me abandonó. Cada vez que sobre-ingenierio un proyecto, cada vez que empujo a través de la frustración de intentar que algo funcione por milésima vez, estoy persiguiendo esa misma mirada de niño asombrado. No se trata solo de future-proofing, ni de ego, ni de ambición técnica. Se trata de mantener viva la chispa.

El balance

Al final, todo vuelve al balance. No toda llamada necesita un middleware para interactuar con una operación. No todo proyecto necesita docenas de servicios. A veces la mejor solución también es la más simple. El principio que más me ayuda es KISS: Keep It Simple, Stupid. Cuando la complejidad es necesaria — por escalabilidad, por mantenibilidad, por aprendizaje — constrúyela. Pero cuando no lo es, la simplicidad casi siempre va a ganar en el largo plazo.

Para llevar

El overengineering no siempre es una pérdida de tiempo. A veces es una inversión en aprendizaje, en construir una base para el futuro, o incluso en alimentar ese ego de desarrollador que nos empuja a crecer. La clave está en reconocer cuándo estás genuinamente haciendo future-proofing — y cuándo solo estás complicando las cosas porque sí. Los mejores codebases son los que balancean ambos: simples donde pueden serlo, sofisticados donde deben serlo. Y la única forma de encontrar ese balance es a veces yéndote demasiado lejos, aprendiendo a la mala, y llevando esas lecciones contigo.