El costo oculto de un alcance mal definido en software
Un desarrollo de software rara vez se encarece por lo que se construye. Se encarece por lo que toca construir dos veces. Y casi siempre la causa está en una conversación que no se dio al arrancar: la de definir bien el alcance.
La pregunta que lo cambió todo
Hace un tiempo nos tocó recibir un desarrollo que ya estaba andando. La plataforma funcionaba: tenía módulos, usuarios, reportes y varias instituciones trabajando sobre ella. El problema no era lo que hacía, sino cómo estaba hecha por dentro.
Todo vivía en una misma base de datos y en las mismas tablas, y lo único que separaba la información de una institución de la de otra era un campo con su identificador. Funcionaba mientras fueran pocos. Pero cuando nos sentamos a pensar en cómo iba a crecer, quedó claro que ese modelo no aguantaba: había que pasar a una arquitectura multitenant de verdad, con los datos de cada organización aislados en su propio espacio.
Ese cambio terminó tocando prácticamente todo. Y a la larga, refactorizar salió más caro que haberlo construido bien desde el primer día. Aquí va lo que aprendimos, desde la doble mirada de quien escribe el código y de quien decide qué se construye.
El alcance es una decisión de arquitectura
Definir el alcance no es hacer una lista de pantallas y botones. Es poner las reglas de juego sobre las que se diseña todo lo demás.
En un proyecto conviven dos tipos de requerimientos. Los funcionales describen lo que hace el usuario: crear un registro, generar un reporte, recibir una notificación. Se pueden ir sumando sprint a sprint, sin mayor lío.
Los estructurales son otra cosa. Definen cómo está hecho el sistema por dentro y son muy difíciles de incorporar después:
- Multitenancy: cómo se separan los datos de cada organización y qué tan aislados deben estar.
- Modelo de permisos: quién ve qué, a qué nivel y con qué jerarquía.
- Trazabilidad y auditoría: qué cambios deben quedar registrados y por cuánto tiempo.
- Integraciones: con qué otros sistemas va a conversar la plataforma. Una buena integración de plataformas se piensa desde el modelo de datos, no se pega al final.
- Requisitos regulatorios: tratamiento de datos personales, retención y consentimiento.
Un requerimiento funcional que se quedó por fuera se resuelve con un ticket. Uno estructural se resuelve con una refactorización. Tener clara esa diferencia antes de escribir la primera línea de código ahorra muchos dolores de cabeza.
De todos en las mismas tablas a un esquema por organización
El modelo original metía a todas las instituciones en la misma base de datos y en las mismas tablas, diferenciadas solo por un identificador. En el papel parece práctico. En la operación, empezó a generar cuatro problemas:
- Riesgo contractual. Varios clientes tenían contratos que exigían que su información estuviera aislada de la de otros negocios. Un filtro por identificador no cumple esa promesa: basta una consulta mal escrita para mezclar datos.
- Cambios que le pegaban a todos. Cualquier actualización del modelo impactaba a todos los clientes al mismo tiempo, lo necesitaran o no.
- Personalizaciones que ensuciaban el modelo. Si un cliente necesitaba un campo propio, la columna se agregaba para todos y quedaba vacía en el resto.
- Consultas cada vez más pesadas. Con miles de registros de múltiples clientes en la misma tabla, cada consulta cargaba con información que no le correspondía.
La salida fue aislar los datos de cada organización en su propio esquema. Es un enfoque sólido cuando el aislamiento importa, pero no es un switch que se prende y listo. Tocó intervenir capa por capa:
- El modelo de datos. Rediseñar dónde y cómo se guarda la información, separando lo que es común a la plataforma de lo que pertenece a cada organización, para que cada esquema pueda evolucionar sin afectar a los demás.
- La resolución del tenant. Cada petición tiene que saber a qué organización pertenece antes de tocar un solo dato.
- Las consultas de cada entidad. Revisarlas una por una para que lean y escriban en el esquema correcto, en lugar de filtrar por identificador de institución.
- Los dashboards. Reconstruirlos para que cada organización vea solo lo suyo, y definir qué vistas consolidadas necesita quien administra la plataforma.
- La migración de lo existente. Sacar los datos de cada institución de las tablas compartidas y llevarlos a su esquema, sin perder información ni frenar a los usuarios.
Ninguno de estos pasos era complejo por sí solo. Lo que pesó fue hacerlos todos sobre un sistema en producción, con clientes reales trabajando encima.
Pasar a multitenant cambió cada capa, del modelo de datos al dashboard
Todos en las mismas tablas
Un esquema por organización
Antes, solo un campo separaba a cada institución. Después, cada petición resuelve primero a qué organización pertenece y solo entonces toca su esquema.
Antes, todas las instituciones compartían tablas y solo un campo las separaba. Después, cada petición resuelve primero a qué organización pertenece y solo entonces toca su esquema.
Por qué refactorizar sale más caro que hacerlo bien desde el inicio
En el papel, aislar los datos de cada cliente debería costar lo mismo al inicio que a mitad de camino. En la práctica no es así, por cuatro razones.
- Se paga dos veces. Cada consulta, cada vista y cada reporte se escribió una vez con un supuesto equivocado y otra vez con el correcto. Ese primer esfuerzo no se recupera.
- Se trabaja sobre datos reales. Un diseño desde cero se prueba con datos de ejemplo. Una refactorización se hace con usuarios activos e información que no se puede perder, lo que obliga a planear migraciones, respaldos y ventanas de cambio.
- El riesgo de regresión está en todas partes. Cuando el cambio toca la forma en que se accede a los datos, cualquier módulo puede romperse. Toca volver a probar todo, no solo lo nuevo.
- El producto se frena. Mientras el equipo rehace la base, no saca funcionalidades nuevas. Ese costo de oportunidad no aparece en ninguna factura, pero el negocio sí lo siente.
La idea de que un cambio cuesta más cuanto más tarde se hace en el ciclo de vida es vieja en la ingeniería de software. Lo que esta experiencia nos dejó claro es que el multiplicador no es igual para todos los cambios: los estructurales crecen mucho más rápido que los funcionales.
Cuando el que programa también define el producto
Desde el rol de product owner, la presión natural es salir rápido: validar con los primeros clientes, mostrar resultados y no construir lo que todavía nadie ha pedido. Es un instinto sano y lo defiendo.
Desde la ingeniería, uno sabe que no todas las decisiones pesan lo mismo. Hay cosas que se cambian en una tarde, como el texto de un botón o el orden de un formulario. Y hay otras que, una vez tomadas, condicionan meses de trabajo: cómo se modelan los datos, cómo se aíslan y cómo se controla el acceso.
La clave está en diferenciar entre construir algo y dejarlo preparado. No hacía falta tener desde el día uno un panel para administrar organizaciones ni un onboarding automático. Pero sí hacía falta que cada cliente tuviera su espacio de datos aislado desde el principio. Eso cuesta poco al arrancar y muchísimo después.
Cuando la misma persona tiene los dos roles, esa tensión juega a favor: quien prioriza el backlog entiende lo que cuesta cada atajo técnico, y quien escribe el código entiende por qué el negocio necesita velocidad. Y cuando ese equilibrio no existe dentro del equipo, una mirada externa de consultoría TIC ayuda a ponerlo sobre la mesa antes de que las decisiones se vuelvan irreversibles.
Siete preguntas antes de escribir la primera línea
No se trata de adivinar el futuro ni de sobrediseñar. Se trata de identificar las decisiones que saldrían caras de cambiar y tomarlas con cabeza fría. Estas son las preguntas que hoy nos hacemos al definir el alcance:
- ¿Cuántas organizaciones van a usar esto en dos años? Si pueden ser varias, el modelo de datos tiene que saberlo desde ya, y no solo con un campo que las diferencie.
- ¿Qué nivel de aislamiento exigen los datos? La sensibilidad de la información, los contratos y la normativa de protección de datos personales definen si basta con un filtro o se necesita separación real.
- ¿Quién necesita ver qué? Roles, jerarquías y alcances de visibilidad, por usuario y por organización.
- ¿Qué se va a reportar y a qué nivel? Los dashboards por cliente y los consolidados de la plataforma se diseñan distinto.
- ¿Con qué otros sistemas se va a conectar? Una API pensada desde el inicio evita duplicar lógica más adelante.
- ¿Qué tanto se va a personalizar por cliente? Si cada uno va a pedir campos o flujos propios, el modelo debe permitirlo sin afectar a los demás.
- ¿Cuál de estas decisiones sería irreversible? Para esas vale la pena invertir tiempo de diseño, aunque la funcionalidad completa llegue después.
Definir bien no es perder tiempo
Una semana extra de análisis al arrancar un proyecto se siente como un retraso. Varias semanas de refactorización a mitad de camino se sienten como un fracaso, y casi siempre salen más caras.
La lección no es construirlo todo desde el principio. Es saber cuáles decisiones definen la forma del sistema y tomarlas antes de que el código las tome por uno.
Aplica igual para una plataforma con decenas de clientes que para un proyecto de diseño web a medida: un alcance bien pensado es lo que deja crecer el producto sin tener que volver a empezar.