Ir al contenido
Juan Ignacio Portilla Kitroser
Caso - SISOC

Un sistema de ingeniería para una plataforma que nunca deja de cambiar

SISOC es el back office de una secretaría nacional de políticas sociales en Argentina. Lidero el equipo que lo construye, y construí el sistema que permite que cinco personas salgan a producción cada semana, cuando los requerimientos cambian cada semana.

Rol
Technical Lead desde nov. 2024 (desarrollador desde jul. 2024)
Equipo
4 desarrolladores + yo, también como desarrollador y devops
Stack
Python, Django, DRF, MySQL, React, TypeScript, Docker, GitHub Actions
Usuarios
~750 personas del Estado, activas
Pull requests
1.750+ mergeados desde nov. 2024, ~670 míos
Estado
En producción - migración en curso
Problema

Cambios grandes, rápidos y baratos, cada semana

SISOC cubre comedores comunitarios, relevamientos de campo, admisiones, centros de infancia, programas alimentarios y de formación laboral, y una vista 360° de cada ciudadano. Lo usan equipos de distintas provincias y áreas: técnicos, coordinadores, legales, contables, auditores.

El organismo público detrás pide cambios grandes, rápidos y baratos. Barato acá significa tiempo: nos piden acortar los plazos dedicando menos a estudiar, validar y ser cautelosos con las decisiones. Los compromisos suelen tomarse antes de que ingeniería los dimensione.

Y el terreno se mueve todo el tiempo. Los requerimientos cambian de una semana a la otra: lo que se acordó esta semana puede ser distinto la siguiente, muchas veces con el trabajo ya empezado.

Contexto

De dónde partí

SISOC nació de un sistema de gestión de ciudadanos existente. No estaba hecho para escalar: apenas cumplía su función y no era estable. No tenía tests, ni linters, ni entornos bajos, ni cultura de pull requests, ni deploys controlados, ni documentación. Las tareas vivían en un grupo de WhatsApp.

La infraestructura es limitada y en parte pertenece a otro equipo del Estado. SISOC además consume sistemas externos que no controla, como el registro nacional de identidad. Y otros sistemas consumen de SISOC: una ticketera, un sistema de comunicaciones y tres aplicaciones de campo.

Mi responsabilidad

Qué hago yo y qué hace el equipo

Coordino prioridades con quienes hablan con los stakeholders y reparto el trabajo entre cuatro desarrolladores y yo. Construí los estándares y las automatizaciones que los sostienen. Reviso y apruebo cada pull request y cada deploy a producción, y mantengo la infraestructura. Lidero las decisiones de arquitectura y las dejo escritas como ADRs.

El equipo construye funcionalidades en todos los módulos. Hizo las tres apps de campo.

Solución

SISOC como mapa de subte

SISOC como mapa de subteRÍO DE LA PLATADjango corekernel - identity - proxyNginxBrowserRENAPERnational identity registryField-management systemTicketing systemWeb pushSMTPSentryCiudadanosComedoresVPSLPASVATCeliaquíaCDICDFDispositivosEspacios ComunitariosDataCalleGestionary más programasUIDF
U - Recorrido del usuarioD - SISOC: core y programasI - Integraciones externasF - Apps de campo del equipo
Decisiones técnicas

Las decisiones que lo sostienen

  1. Calidad automática, no negociable

    Por qué - Bajo presión constante, todo lo opcional se saltea. Por eso el estándar vive en el CI: cada pull request pasa linters, tests con un gate de cobertura del 75%, chequeos de arquitectura y escaneo de secretos antes de que yo lo revise.

    Costo

    Los pull requests tardan más en mergearse. Lo aceptamos a cambio de no discutir calidad en cada cambio.

  2. Un tren de releases semanal

    Por qué - Los stakeholders necesitan un ritmo acelerado. Cada jueves una release congelada y etiquetada pasa de QA a staging y a producción, con mi aprobación manual al final.

    Costo

    Los cambios urgentes esperan al tren y todos respetan el proceso diseñado, salvo que justifiquen un hotfix.

  3. Monolito modular antes que servicios

    Por qué - No podíamos frenar la entrega para reescribir. Primero hicimos modular el monolito: un ratchet de import-linter con línea base y muchos ADRs chicos que cortan una dependencia cada uno.

    Costo

    Más lento que una separación de golpe, pero el sistema siguió saliendo cada semana.

  4. Backends por dominio en un monorepo

    Por qué - Un kernel compartido y un backend por dominio, cada uno con su propia imagen construida desde el SHA del commit. El core de Django hace de proxy, y los deploys y rollbacks son por dominio.

    Costo

    El aislamiento todavía es por proceso, no por base de datos. El proxy es un punto único de falla. Ambos están escritos como deuda aceptada.

  5. Frontends React con tipos desde la API

    En curso

    Por qué - Las pantallas nuevas son React y TypeScript, con tipos generados desde el esquema OpenAPI, para que frontend y backend no se desalineen en silencio.

    Costo

    Dos stacks de UI conviven durante la migración. Se está migrando el frontend mientras se siguen usando los templates de Django.

  6. Documentación como fuente de verdad, para personas y agentes

    Por qué - Primero van las specs y los ADRs; los docs de cada PR y el changelog se generan solos. Los agentes de IA trabajan dentro de los mismos límites que las personas, y los ADRs registran qué decisiones fueron mías y cuáles una recomendación de un agente.

    Costo

    Escribir primero lleva tiempo en cada cambio. Es lo que hace posible el trabajo asincrónico y revisable lo que produce un agente, y hace que ahorrarnos tiempo de programación no nos robe el control.

Resultado

El sistema en el que trabaja el equipo hoy

No hay números de antes y después. Lo que sí se puede mostrar es el sistema: qué cambió y qué tiene que pasar cada cambio.

Cuando lleguéTareas en un grupo de WhatsAppHoyTablero kanban, Discord, weekly
Cuando lleguéSin testsHoyTests unitarios y e2e, gate de cobertura del 75% en CI
Cuando lleguéSin linters ni estándaresHoyLinters, estándares escritos, límites entre módulos verificados en CI
Cuando lleguéDeploys directo a producciónHoyQA → staging → producción, release cada jueves
Cuando lleguéSin documentaciónHoySpecs y ADRs como fuente de verdad

Todo cambio en SISOC pasa por esto

release: cada jueves
PRCI
    lintblack, pylint, djlint, encoding
    testssmoke + pytest, gate de cobertura 75%
    migrationschequeo de migraciones
    mysql compattests contra MySQL real
    architecturelímites entre módulos (import-linter)
    frontendfronts React: tipos, tests
    secretsescaneo de secretos (gitleaks)
    release sanitychequeos de deploy, esquema, estáticos
    pr docsdocs del PR y changelog generados
reviewreviso y apruebo cada PR
Entrega
    freeze + tagrelease candidate etiquetada
    QAentorno de pruebas
    stagingpreproducción
    producciónaprobación manual, mía
Historia - Reporte de campo - incidente en producción

Miércoles, 2 a.m. Una migración falla a la mitad.

Qué pasóUna migración de Django que había pasado en los entornos bajos falló con los datos reales de producción. El esquema quedó migrado a medias e incompatible con el código anterior.
Qué hiceNo tenía acceso a los backups y no había nadie de infraestructura de guardia. Volví el código atrás y reconstruí los datos afectados desde un export local que había hecho días antes para pruebas. Algunos registros faltaron hasta que infraestructura se conectó y pude restaurarlos.
Qué cambióMe dieron acceso completo a los backups. Agregamos un chequeo de migraciones al CI. El nuevo deploy salió preparado para ese error exacto.

Qué me llevé

Juan Ignacio Portilla Kitroser
Contacto

Hablemos

Software engineer enfocado en backend: Python, Django y DRF, con React y Next.js en el frontend. Construyo y mantengo sistemas en producción con reglas de negocio complejas y muchas integraciones, y uso herramientas de IA todos los días sin bajar la vara.

  • Disponible ya - contractor o full-time
  • Inglés fluido
  • Superposición completa con el horario de la costa este de EE.UU. (GMT-3)