
Una sola fuente de verdad: cómo el sitio se arma solo desde el catálogo
Teníamos los servicios cargados en la base y escritos otra vez en el sitio. Cada cambio había que hacerlo dos veces, y siempre había un lugar que quedaba viejo.
Idempotencia, migraciones, borrado lógico, fallar temprano. Conceptos de hace décadas que se volvieron críticos justo cuando quien escribe el código no siempre es humano.

Circula la idea de que con agentes escribiendo código los fundamentos importan menos. Nuestra experiencia es exactamente la opuesta: importan más, porque ahora hay algo que escribe rápido, sin cansarse y sin la intuición que da haberse quemado.
Estos son los cuatro que más veces nos salvaron.
Una operación idempotente es la que podés correr diez veces y deja el mismo resultado que si la corrieras una.
Con procesos largos y reintentos automáticos, esto dejó de ser elegancia académica. Un flujo que se reintenta después de una caída va a repetir pasos. Si el paso "crear la suscripción" no es idempotente, el cliente termina con tres suscripciones y una conversación incómoda.
Nuestro seed de datos es idempotente. Nuestras migraciones de datos son idempotentes. Las tareas de los playbooks chequean si ya se hicieron antes de hacerse. No es prolijidad: es la única forma de que reintentar sea seguro.
Es tentador entrar a la base de producción y correr un ALTER TABLE. Anda, tarda diez segundos y nadie se entera.
El problema aparece después: el entorno local y el de producción divergen en silencio, y el día que descubrís la diferencia es siempre el peor día posible.
Toda modificación de esquema pasa por una migración versionada. Incluso las de datos. La semana pasada reorganizamos la estructura de servicios del catálogo, que implicaba mover un producto de categoría y crear una tabla nueva. Podría haber sido cinco minutos de SQL a mano. Fueron tres migraciones escritas, revisadas y aplicadas en orden. Cuando toque hacerlo en producción, va a ser un comando y no un acto de fe.
No borramos registros. Marcamos con is_active: false o status: deleted.
La razón inmediata es la obvia: recuperar algo borrado por error. Pero la que resultó más valiosa es otra. Un registro borrado de verdad se lleva su historia: quién lo creó, qué pedidos tenía asociados, por qué existía. Con borrado lógico esa historia queda, y la podés consultar cuando un cliente pregunta por algo de hace ocho meses.
Hay un costo real: todas las consultas tienen que filtrar. Se paga con gusto.
Nuestros servicios no arrancan si falta un secreto. No arrancan con un valor por defecto, no escriben una advertencia y siguen: no arrancan.
Esto vino de un episodio clásico. Había valores de respaldo para desarrollo, del estilo dev_secret. Cómodos, hasta que un despliegue mal configurado llegó a producción con el respaldo puesto, funcionando aparentemente bien y firmando tokens con un secreto que estaba en el repositorio.
Sacamos todos los valores por defecto. Ahora, si falta algo, el proceso muere en el arranque con un mensaje que dice exactamente qué falta. Es molesto la primera vez que configurás el entorno y es una tranquilidad todos los días siguientes.
Un agente escribe código plausible a gran velocidad. Va a proponer el DELETE en vez del borrado lógico, el cambio de esquema a mano en vez de la migración, el valor por defecto en vez del error. No por descuido: porque son soluciones razonables si no conocés la historia del sistema.
Los fundamentos son justamente esa historia comprimida. Y alguien tiene que conocerla para saber cuándo lo plausible no alcanza.

Teníamos los servicios cargados en la base y escritos otra vez en el sitio. Cada cambio había que hacerlo dos veces, y siempre había un lugar que quedaba viejo.

Un agente que recuerda todo es un agente lento, caro y confundido. Diseñar qué se descarta resultó más difícil que diseñar qué se guarda.
Contanos qué necesitás y te decimos cómo lo encararíamos. En minutos, no en semanas.
Sin compromiso. La primera charla es gratis y respondemos al toque.