Una plataforma de pagos debe explicar qué dinero movió, qué trabajo aceptó y qué resultados siguen pendientes cuando una llamada pierde su respuesta. El mismo sistema puede responder en tiempo real y cerrar obligaciones mediante procesos batch. La operación conecta esas dos escalas: una petición individual y un ciclo cuya integridad depende de millones de registros.
Este es un caso hipotético de estudio, construido a partir de responsabilidades de ingeniería y SRE: transacciones a gran escala, tres centros de datos propios y AWS, Kubernetes u OpenShift, procesamiento real-time y liquidación batch, observabilidad, secretos y automatización. Las decisiones y cifras siguientes son supuestos ilustrativos. No describen una arquitectura empresarial real, un benchmark ni una certificación de cumplimiento regulatorio.
El recorrido sigue una operación desde su admisión hasta su asiento y su liquidación. Cada etapa declara una autoridad, una evidencia durable y una respuesta al fallo. El objetivo es poder explicar por qué una recuperación conserva el resultado financiero, además de volver a poner procesos en verde.
Para un repaso autocontenido de los contratos y del diagnóstico, puede consultarse la hoja de repaso SRE.
Requisitos, participantes y fronteras
Supongamos una red de participantes autorizados que presenta transferencias en una moneda determinada. La plataforma valida instrucciones, registra movimientos internos y agrupa obligaciones para liquidarlas con un sistema externo. Un pago interno confirmado crea una obligación durable; no demuestra que todas las posiciones del ciclo ya se hayan liquidado externamente.
Las funciones son admitir una instrucción, consultar su estado, registrar una decisión financiera, publicar eventos y cerrar ciclos. También se necesitan consultas de conciliación y mecanismos controlados de corrección. Un reembolso, una reversión contable y la cancelación de una instrucción todavía pendiente representan acciones distintas.
| Actor | Responsabilidad y frontera |
|---|---|
| Participante | Presenta instrucciones dentro de cuentas, monedas y facultades autorizadas. |
| API de pagos | Valida identidad, contrato e idempotencia; comunica aceptación o resultado. |
| Núcleo financiero | Decide movimientos y disponibilidad bajo una transacción autoritativa. |
| Workers y coordinador batch | Preparan trabajo recuperable y ciclos; no inventan movimientos para resolver errores. |
| Sistema externo de liquidación | Acepta instrucciones y proporciona confirmaciones bajo su propio contrato. |
| Operación SRE | Detecta impacto, ejecuta recuperación acotada y conserva evidencia. |
Se acuerdan invariantes antes de elegir componentes: una instrucción lógica no puede producir dos efectos financieros válidos; cada asiento está equilibrado por moneda; una salida externa debe vincularse a una intención registrada; y una incertidumbre conserva dueño y ruta de resolución. La autorización se evalúa por participante y operación, no sólo porque la petición tenga un certificado válido.
El framework de diseño ayuda a completar primero el flujo básico. Disponibilidad, latencia y durabilidad se asignan a operaciones concretas. Consultar una proyección retrasada puede ser aceptable; decidir saldo disponible o repetir una salida de dinero exige consultar la autoridad adecuada.
Capacidad con unidades y presupuestos separados
Tomemos seis millones de instrucciones lógicas por día como supuesto propio. El promedio sería 6,000,000 / 86,400 ≈ 69.4 instrucciones/s. Un pico ilustrativo ocho veces mayor sería aproximadamente 556 instrucciones/s. Ambos valores son entradas del ejercicio: no predicen capacidad ni sustituyen una distribución horaria, tamaño de mensajes, concentración por cuenta y mezcla de operaciones.
Si cada instrucción produce dos eventos de un KiB, se generan unos doce millones de eventos y 11.4 GiB diarios de payload, antes de índices, replicación, metadatos y compresión. Una llamada de estado, un reintento y una instrucción nueva consumen trabajo diferente. Contarlas todas como nuevos pagos distorsionaría volumen, coste y resultado.
Procesar seis millones de registros de un ciclo en cuarenta minutos requeriría una tasa media de 6,000,000 / 2,400 = 2,500 registros/s. Es un objetivo de lectura y transformación que debe medirse; no implica enviar 2,500 transferencias externas por segundo. El neteo puede producir muchas menos instrucciones, y el proveedor tiene límites y ventanas propios. El tiempo disponible incluye validación, carga, confirmación y conciliación.
Se separan presupuestos para tráfico online, preparación batch, publicación y recuperación. Como ejemplo de planificación, un límite medido de 160 conexiones de aplicación al primario podría repartirse en 80 online, 20 batch, 20 de reconciliación y 40 reservadas para tareas autorizadas y operación. No es una recomendación universal para Postgres: CPU, IO, consultas, locks y memoria determinan el límite real. Las réplicas y sus pools se dimensionan aparte.
Los pools reutilizan conexiones y acotan espera. Deben observarse conexiones activas, cola para adquirirlas y transacciones abiertas; abrir más conexiones no aumenta necesariamente trabajo útil. El número de pods multiplicado por el máximo de cada pool puede superar el presupuesto global durante un rollout. El modo de pooling debe ser compatible con estado de sesión y características del driver.
La admisión reserva margen para recuperar pendientes aunque aumente la demanda. Batch puede reducir concurrencia al competir por el mismo almacenamiento. Las colas tienen límites por cantidad, bytes y edad, y los deadlines incluyen la espera. La prueba relevante combina pico online, cierre de ciclo y una dependencia lenta; no mide cada componente sólo cuando trabaja aislado.
Tres centros de datos y AWS con una autoridad financiera
Elegimos un núcleo con un solo escritor financiero. En el DC uno reside el primario; el DC dos conserva una réplica síncrona seleccionada. El ACK de una escritura que el contrato llama confirmada se devuelve después de la persistencia local y de la confirmación durable exigida en esa réplica. Esperar flush remoto no implica que cualquier lector remoto ya vea la transacción aplicada.
DC tres aporta lectura permitida, recuperación y copias bajo un contrato separado. AWS ejecuta workers, analítica y observabilidad, y conserva una opción de DR mediante replicación asíncrona. Cada sitio tiene clústeres Kubernetes u OpenShift independientes. No estiramos un único clúster de control entre los tres DC y AWS ni permitimos que toda réplica acepte movimientos financieros.
--- config: look: handDrawn --- flowchart TD participant["Participante autorizado"] --> entry["Entrada<br/>Identidad y admisión"] entry --> api["API de pagos<br/>Clúster independiente por sitio"] api --> core[("DC uno<br/>Ledger, estados y outbox<br/>Escritor único")] core -->|"Persistencia síncrona"| sync[("DC dos<br/>Réplica seleccionada")] sync -->|"Confirmación durable"| core core -->|"ACK bajo el contrato"| api core -.->|"Replicación de recuperación"| recovery[("DC tres<br/>Lectura y recuperación")] core -.->|"Replicación asíncrona"| dr[("AWS<br/>Copia para DR")] core --> relay["Relay recuperable"] relay --> stream["Eventos retenidos"] stream --> workers["AWS<br/>Workers y preparación batch"] workers --> control["Comandos validados<br/>a la autoridad financiera"] control --> core workers --> telemetry["Señales de servicio<br/>Datadog u Observe"]
La WAN forma parte de la latencia y de la disponibilidad de escritura. Si desaparece la réplica requerida, mantener el contrato puede exigir pausar confirmaciones. Un cambio a durabilidad menor necesita una decisión explícita y consecuencias comunicadas; no debe ocurrir silenciosamente para mejorar un dashboard. Los destinos de entrada y balanceo tampoco adquieren autoridad sobre el dinero por estar saludables.
El escritor único simplifica la propiedad de invariantes y reduce conflictos financieros entre sitios. Introduce una dependencia de coordinación y un techo que debe medirse. Se pueden escalar lectores y trabajo derivado; distribuir escrituras requiere después una partición de dominio que preserve operaciones entre cuentas. Una etiqueta «active-active» no resuelve esa decisión.
La replicación tiene un ámbito de fallos. El ACK síncrono protege la historia confirmada bajo las condiciones escogidas; no protege contra todo borrado lógico ni la pérdida simultánea de las copias necesarias. DR asíncrono puede perder historia reciente. Los respaldos restaurables conservan otra vía, con posición, claves y procedimiento comprobados.
Entidades y ledger autoritativo
El esquema se diseña desde accesos e invariantes. El journal del ledger es append-only: los movimientos confirmados no se corrigen sobrescribiendo cantidades. Una corrección autorizada produce otro asiento vinculado al original. Estados de procesamiento y proyecciones pueden cambiar bajo reglas explícitas; no son el journal inmutable.
| Entidad | Datos y restricciones principales |
|---|---|
| Participante y cuenta | Identificadores no nulos, moneda, estado y permisos; referencias válidas. |
| Operación | operation_id único y NOT NULL, participante, huella de intención y estado. |
| Asiento | journal_id único y NOT NULL, operación de origen, moneda y fecha de negocio. |
| Línea del asiento | entry_id único y NOT NULL, journal, cuenta y cantidad entera firmada. |
| Reserva de disponibilidad | Cuenta, operación, importe, versión y regla de liberación. |
| Intento externo | attempt_id único y NOT NULL, referencia estable, estado y evidencia. |
| Evento y outbox | event_id único y NOT NULL, entidad, versión, payload y publicación pendiente. |
| Ciclo y membresía | Identidad del ciclo, reglas versionadas, fronteras de fuente y registros incluidos. |
Las cantidades se expresan en unidades menores enteras por moneda, con un tipo capaz de contener el rango permitido y controles de overflow. El número de decimales pertenece a metadatos versionados de la moneda; no se supone que todas usan centavos. Entrada, redondeo, fees y conversión tienen reglas explícitas. Sumar cantidades de monedas distintas carece de significado financiero.
Para cada journal confirmado y moneda, la suma firmada de líneas debe ser cero. Además se valida disponibilidad cuando el producto no permite sobregiro. Estas invariantes abarcan filas: un CHECK(sum(...)) ordinario no ofrece esa protección en Postgres. Tampoco basta comprobar el total en la aplicación y escribir después sin coordinación.
La frontera transaccional autoritativa controla todos los caminos de escritura. Un servicio de posting con permisos acotados valida el conjunto completo, bloquea las cuentas necesarias en orden estable o utiliza aislamiento apropiado, inserta líneas y actualiza disponibilidad y estado en la misma transacción. Si se usa Serializable, se contempla abortar y reintentar la transacción completa. Las restricciones, aislamiento y autoridad trabajan conjuntamente.
Una unicidad que admita identificadores nulos debilitaría la deduplicación, por eso los IDs relevantes son también NOT NULL. El journal referencia la operación de negocio, además de cualquier clave de reintento. Cambiar una clave no debe permitir una segunda aplicación del mismo movimiento. Las consultas de participante comprueban scope sobre cada cuenta y recurso; conocer un ID no concede acceso.
API, estados y evidencia de una decisión
Una interfaz conceptual ofrece POST /payments, GET /payments/{operation_id} y consultas autorizadas de ciclos y discrepancias. Las correcciones se presentan como operaciones nuevas y explícitas, referenciadas al movimiento original. El servidor calcula facultades y condiciones, y no acepta cantidades o destinos únicamente porque una interfaz cliente los mostró.
La petición incluye una clave estable vinculada al participante, la operación y la huella del payload. Una repetición compatible obtiene la decisión registrada; la misma clave con otra intención produce conflicto. Un registro pendiente conserva estado consultable. HTTP 202 puede comunicar aceptación, pero no confirma un movimiento ni una liquidación.
| Estado | Lo que permite afirmar |
|---|---|
RECEIVED | Existe intención durable; todavía no hay resultado financiero final. |
VALIDATED | Contrato y facultades comprobados bajo las condiciones registradas. |
RESERVED | Disponibilidad reservada; no equivale a liquidación externa. |
POSTED | El movimiento local aplicable quedó confirmado bajo su política de durabilidad. |
REJECTED | Decisión definitiva con causa; un nuevo intento necesita intención legítima. |
CORRECTION_PENDING | Existe una corrección autorizada cuyo progreso se sigue por separado. |
La liquidación de obligaciones y sus intentos externos tienen estados separados, como PREPARED, SENT, UNKNOWN, CONFIRMED o FAILED_FINAL. Una respuesta de transporte exitosa no sustituye la confirmación de negocio. Si una ruta de pago requiere un efecto externo antes de su resultado final, su máquina de estados conserva ese requisito; no reutiliza POSTED para ocultarlo.
En una transacción corta se registra o reconoce la operación, se valida la transición esperada, se protege la disponibilidad y se confirma el efecto local junto con la outbox. La condición sobre versión y estado evita que dos workers decidan caminos incompatibles. Un upsert puede resolver una carrera local sobre unicidad; no vuelve atómica una transferencia hacia otro sistema.
La cancelación compite con ejecución y reconciliación. Debe consultar el estado y conservar una decisión condicionada, en vez de borrar el pendiente y empezar de nuevo. El ACK perdido después del commit se recupera por la misma identidad. Esa es la diferencia entre repetir una petición y crear otra operación.
Eventos y efectos externos con resultado incierto
El journal, el cambio de estado y la intención de publicar se confirman dentro de la misma frontera local. El relay lee outbox, publica y registra progreso. Si cae después de publicar y antes del checkpoint, puede repetir el evento. Los consumidores conservan event_id y coordinan deduplicación, efecto y checkpoint dentro de la frontera que realmente poseen.
--- config: look: handDrawn --- flowchart TD accepted["Operación autorizada<br/>Identidad estable"] --> local[("Transacción local<br/>Decisión y outbox")] local --> relay["Relay<br/>Publicación recuperable"] relay --> event["Evento lógico<br/>Puede entregarse otra vez"] event --> view["Consumidor<br/>Deduplicación y proyección"] local --> intent[("Intención externa durable<br/>Referencia original")] intent --> send["Despachar fuera de la transacción"] send --> external["Sistema externo"] external -->|"Resultado verificado"| result[("Registrar resultado<br/>Transición condicionada")] send -->|"Respuesta perdida"| unknown["Resultado desconocido"] unknown --> reconcile["Consultar y reconciliar<br/>Referencia original"] reconcile --> external reconcile --> result
La intención externa queda durable antes de llamar al proveedor. El I/O ocurre fuera de una transacción larga; luego otra transacción registra la evidencia y aplica una transición válida. Ni una outbox ni dos commits locales hacen atómico el conjunto de base y API externa. Se conserva información suficiente para recuperarlo cuando falla entre etapas.
UNKNOWN significa que no sabemos si el efecto ocurrió. No se reenvía con una identidad nueva, no se desbloquean fondos por intuición y no se compensa como si el proveedor hubiera rechazado. Primero se consulta o se reintenta bajo su idempotencia, alcance y ventana de retención. Si esa garantía terminó, se concilia evidencia antes de abrir otro intento. La compensación es un nuevo efecto autorizado, también recuperable.
El orden por entidad necesita versión o secuencia, publicación y procesamiento compatibles. La clave de partición ayuda a conservar esa secuencia, pero no establece orden global ni atomicidad entre cuentas. Las colas conservan trabajo; el modelo de broker se elige por replay, routing y garantías necesarias. Ninguno certifica por sí solo un cobro.
Claims o leases permiten recuperar trabajo abandonado. Una reclamación con SKIP LOCKED puede repartir filas independientes, sin prometer justicia ni terminar en orden. La transacción de claim es corta y deja propietario, versión y vencimiento. El worker anterior puede volver; su confirmación tardía se valida contra la propiedad vigente, y el efecto externo sigue necesitando su propio contrato.
Una proyección reconstruida utiliza eventos para recuperar vistas, no para volver a ejecutar salidas de dinero. Snapshot, posición y retención determinan desde dónde se puede continuar. Saltar un mensaje financiero inválido y procesar dependientes puede romper la secuencia: se aísla la entidad afectada, se conserva evidencia y se resuelve el hueco.
Batch: cerrar un conjunto demostrablemente completo
El ciclo define un calendario versionado: zona horaria, días hábiles, cutoff, ventana de confirmación y tratamiento de excepciones. La fecha de negocio puede diferir del timestamp de llegada. Un cambio de horario o calendario no modifica silenciosamente qué pertenece a un ciclo ya sellado. Las reglas proceden del contrato acordado con los participantes y el sistema externo.
Para preparar un ciclo se identifica el conjunto de movimientos elegibles y sus fronteras de fuente. Un source watermark representa progreso comprobado por partición o productor, con secuencias, versiones y manifests de cierre esperados. Ver el mayor timestamp no demuestra completitud: pueden faltar eventos anteriores, haber reloj desajustado o llegar registros fuera de orden.
Se contrasta cada fuente esperada con su secuencia cubierta y sus gaps. Los saltos legítimos por abortos o reservas de números necesitan explicación bajo el protocolo de la fuente; no se confunden con eventos pendientes. Si no puede demostrarse una frontera, el ciclo conserva la excepción. Un consumidor que vio un evento reciente no declara por ello terminados a todos los demás.
--- config: look: handDrawn --- flowchart TD calendar["Calendario y cutoff<br/>Reglas versionadas"] --> boundary["Fronteras esperadas de fuente"] boundary --> gaps{"¿Secuencias y manifests completos?"} gaps -->|"No"| exception["Excepción con dueño<br/>Esperar o resolver el hueco"] gaps -->|"Sí"| membership["Membresía determinista<br/>Registros elegibles"] membership --> seal[("Manifest sellado<br/>Conteos, totales y checksum")] seal --> export["Artefacto inmutable<br/>Versión y referencia"] export --> intent[("Intención de envío durable")] intent --> dispatch["Enviar con identidad estable"] dispatch --> confirm["Confirmación de negocio"] dispatch -->|"Resultado incierto"| lookup["Consultar referencia original"] lookup --> confirm confirm --> reconcile["Conciliar membresía<br/>Importes y posiciones"] reconcile --> close["Cerrar ciclo o registrar discrepancias"]
La membresía conserva las identidades incluidas, versiones, moneda y regla de elegibilidad. Se enumera desde un snapshot consistente o una frontera de journal inmutable que permita reproducirla. Puede construirse en chunks con checkpoints y verificaciones. El sellado final comprueba fronteras, membresía y totales bajo coordinación corta; no deja una transacción abierta durante horas para generar y subir un archivo.
El manifest sellado incluye identidad del ciclo, versión de reglas, fuentes esperadas, fronteras cubiertas, conteos, sumas de débito y crédito por moneda y referencias de artefactos. Una vez sellado, no cambia por la llegada de otro evento. Una versión corregida conserva vínculo con la anterior y aprobación de la modificación. El neteo respeta moneda y participante, y registra cómo cada posición se deriva de los movimientos incluidos.
El checksum verifica que los bytes observados correspondan al artefacto esperado. No demuestra que el archivo incluya todas las operaciones ni que su emisor esté autorizado. Se necesita validar esquema, membresía, control totals, identidad y autenticidad. Un total neto cero puede ocultar dos movimientos ausentes que se cancelaban entre sí; por eso también importan IDs, conteos y fuentes completas.
Se conserva un artefacto inmutable y su versión mediante almacenamiento de objetos. Escribir el objeto y actualizar la base no constituye una transacción compartida. La intención y el estado de preparación permiten reconciliar un upload terminado cuyo registro falló, o un registro preparado cuyo archivo falta, sin producir otra instrucción de liquidación.
El envío distingue acuse de transporte, aceptación del formato, aceptación de negocio y liquidación confirmada. La respuesta puede ser parcial por instrucción: se conservan sus identidades y estados, en lugar de reenviar todo el archivo como nuevo. La conciliación compara manifest, confirmaciones y posiciones del sistema externo, clasifica diferencias y exige evidencia antes de dar el ciclo por cerrado.
Los late arrivals mantienen su identidad y fecha original. Según la regla acordada, entran en otro ciclo o en un ajuste explícito; no se añaden clandestinamente al manifest anterior. Se mide su cantidad, edad e impacto. Cerrar a tiempo con huecos desconocidos no equivale a liquidar correctamente, y esperar sin dueño tampoco es una política de recuperación.
Failover: cercar antes de promover y volver a enviar
Un sitio inaccesible para el operador puede seguir vivo y aceptar conexiones por otro camino. Cambiar DNS o readiness no excluye al escritor anterior. Tampoco basta escribir una nueva generación en la base promovida: un proceso aislado que todavía ve la base antigua puede continuar operando contra ella.
El mecanismo elegido debe producir exclusión efectiva: liderazgo por quorum con pérdida de facultades y watchdog, fencing operativo del sitio anterior o una garantía validada del motor y su despliegue. Se ensaya que la ruta antigua ya no puede confirmar escrituras. Si esa prueba no existe, se pausa promoción o escritura financiera. Una lease que vence sin detener al dueño anterior no satisface ese contrato.
Antes de promover se identifican la historia durable y la posición de la réplica candidata. Se registran decisión, versión y evidencia de cerco. La aplicación conserva IDs y consulta decisiones existentes al reconectar. Si se pierde la réplica síncrona requerida, no se comienza a confirmar con una sola copia de forma silenciosa: se incorpora y alcanza DC tres bajo una política comprobada, o se pausan ACKs de nuevas escrituras.
El cerco de egress es otro problema. Un rail que no valida tokens de propietario no queda protegido porque el nuevo ledger tenga líder. Hay que detener la ruta de despacho anterior, invalidar sus facultades cuando corresponda y reconciliar intentos en vuelo antes de reactivar salida de dinero. Las referencias originales permiten preguntar qué ocurrió. Rotar una credencial tampoco demuestra que una petición ya aceptada dejó de producir efectos.
| Modelo de fallo | Objetivo hipotético y condición |
|---|---|
| Caída de un DC con la historia confirmada disponible | RTO objetivo de veinte minutos; conservar todos los ACKs bajo la política síncrona vigente y demostrar exclusión. |
| Partición WAN hacia la réplica requerida | Pausar confirmaciones antes de incumplir durabilidad; recuperar conectividad o reconfigurar una réplica alcanzada y verificada. |
| Pérdida de los DC que conservan la historia síncrona | DR en AWS con RTO objetivo de cuatro horas y RPO objetivo de cinco minutos; contrastarlos con lag y restauración reales. |
| Borrado lógico o corrupción propagada | Restauración desde copia válida y replay verificado; objetivos dependientes de detección, backups y posición disponible. |
Estos son objetivos de este ejercicio, no resultados prometidos. La copia asíncrona puede estar más atrasada que el RPO objetivo. Antes de reactivar egress se contrastan journal recuperado, intentos originales, manifests y evidencia externa. Si faltan referencias o hay discrepancias sin resolver, el flujo afectado permanece retenido. Reconstruir una vista no autoriza repetir instrucciones de dinero.
El ensayo mide detección, decisión, cerco, promoción, reconexión y validación funcional. También mide pérdida observada y pendientes recuperados. Los plazos y propietarios tardíos ayudan a identificar qué puede continuar después de una recuperación; no sustituyen el mecanismo que impide dos decisiones financieras válidas.
Operar workloads, conexiones y secretos
Cada clúster Kubernetes u OpenShift administra su propio control y sus workloads. La colocación distribuye réplicas de servicios según dominios de fallo. Una réplica de aplicación adicional conserva disponibilidad sólo si puede atender con sus dependencias y el contrato financiero vigente. El ledger necesita operación y almacenamiento específicamente ensayados; un StatefulSet no aporta por sí solo durabilidad entre DC.
Los requests expresan recursos para scheduling; los limits establecen límites de consumo donde aplica su mecanismo. Se comprueban memoria, CPU, throttling y terminaciones, incluyendo sidecars y buffers. HPA utiliza señales y tiempos de reacción: no arregla un lock caliente ni permite exceder el pool global. El máximo de réplicas se relaciona con presupuesto de conexiones y capacidad medida de las dependencias.
Readiness decide si el pod puede atender el tráfico previsto. Liveness detecta ciertas situaciones que justifican reiniciarlo; consultar agresivamente toda dependencia puede provocar reinicios en cadena. Un PDB limita algunas interrupciones voluntarias, pero no evita todas las pérdidas de pods o sitios. El rollout también considera capacity temporal y distribuciones que no colocan todos los supervivientes en el mismo fallo.
El draining detiene admisión nueva y permite terminar trabajo acotado antes de cerrar. Para un consumer, confirma únicamente efectos durables; si no termina, deja recuperación bajo la misma identidad. Los plazos de retiro, señales de terminación y ventanas de conexión deben concordar. Cortar la respuesta después del commit deja una incertidumbre recuperable, no una prueba de que el pago no ocurrió.
Diagnosticar red exige separar capas: resolución DNS, conexión TCP, negociación TLS y contrato de aplicación. Un nombre correcto puede resolver a un destino que no responde; una conexión puede establecerse y fallar durante TLS. La prueba TLS valida CA esperada, nombre del host y resultado de verificación. SNI sólo comunica un nombre; enviarlo no demuestra confianza ni hostname válido.
mTLS acredita una identidad de certificado bajo las autoridades aceptadas. La aplicación todavía comprueba que ese participante puede ejecutar esa operación sobre esa cuenta. Las identidades del servicio, del job de mantenimiento y del operador se distinguen; acceder a la red privada no equivale a permiso financiero. Los timeouts y reintentos de cada salto respetan el deadline total.
Vault participa en la entrega de secretos y certificados bajo policies e identidades de workload. Se define quién puede obtener qué material, por cuánto tiempo y qué pasa al fallar renovación o acceso. La aplicación protege copias en memoria y evita imprimirlas. La política de emergencia conserva autorización y auditoría; no distribuye una clave administrativa compartida para resolver conectividad.
Una rotación prepara material nuevo, permite una convivencia deliberada y verifica que los workloads lo cargaron. Se comprueban nuevas conexiones y conexiones existentes, reload o reinicio controlado, raíces y cadenas confiables. Después se retira el material anterior según su contrato y se prueba que ya no permite el acceso esperado. Certificados expirados, credenciales revocadas y sesiones ya abiertas pueden tener comportamientos distintos.
También se ensaya una rotación mientras corre batch y un período sin Vault. La respuesta puede ser servir con material todavía válido, limitar trabajo o pausar una ruta; nunca asumir una renovación infinita. Identidad, cifrado y recuperación complementan este diseño sin convertir una policy IAM en autorización de negocio ni equiparar KMS con Vault.
Entrega de infraestructura, aplicación y automatización
Los cambios de infraestructura, aplicación y runbooks siguen revisión y validación. IaC permite examinar intención y radio de impacto; el state, sus locks y su acceso tienen un contrato propio. Un apply parcial requiere reconciliar recursos efectivos. No se mezcla una reparación manual del ledger con un despliegue de plataforma sólo porque ambos estén en el mismo repositorio.
La aplicación se construye una vez y se promueve por digest de imagen, conservando commit, configuración y evidencia de pruebas. Tags mutables no identifican los bytes evaluados. Se verifican contratos de API, compatibilidad de eventos, transiciones, concurrencia, migraciones y recuperación. Los controles de seguridad aportan señales; no certifican que un artefacto carezca de fallos.
--- config: look: handDrawn --- flowchart TD change["Cambio revisado<br/>Infraestructura, aplicación o runbook"] --> validate["Pruebas de contrato<br/>Seguridad e invariantes"] validate --> artifact["Artefacto identificable<br/>Imagen por digest"] artifact --> gate["Identidad temporal<br/>Gate y alcance del entorno"] gate --> candidate["Despliegue acotado<br/>Compatibilidad comprobada"] candidate --> evidence["Señales de servicio<br/>y resultado financiero"] evidence --> decide{"¿Criterios satisfechos?"} decide -->|"Sí"| extend["Ampliar y observar"] decide -->|"No"| stop["Detener expansión<br/>Recuperación compatible"] incident["Incidente con impacto"] --> runbook["Runbook determinista<br/>Precondiciones y permisos"] runbook --> evidence stop --> evidence
El pipeline usa OIDC o una identidad temporal compatible con su plataforma real, emisor, audience y claims. No se copian claims de GitHub a otro runtime. La trust policy autoriza asumir una identidad; sus permisos limitan el cambio posterior. Entornos, gates y coordinación impiden releases concurrentes incompatibles. Cancelar un job no demuestra que una operación remota se revirtió.
Para extender el patrón a equipos enterprise, el golden path es un contrato versionado de entrega, identidad, telemetría y recuperación, con owner de plataforma y owner del servicio. Cada versión define interfaces, pruebas de conformidad y excepciones con responsable. Un adaptador legacy conserva IDs, estados y evidencia del flujo existente, y expone esas interfaces sin reescribir su núcleo. La adopción comienza en una ruta acotada, valida compatibilidad y permite reversión antes de ampliar participantes o servicios. Los equipos comparan la versión utilizada y resultados de las pruebas; las excepciones tienen seguimiento. Así se avanza por pasos verificables, conservando ownership y evitando una migración big bang.
Para este caso elegiríamos un canary acotado de servicios stateless, con separación de participantes de prueba y ausencia de efectos financieros duplicados. La ampliación exige evidencia de resultados, capacidad y pendientes. Blue-green sería otra opción si su convivencia y rollback son compatibles; no es un requisito del caso. El writer y las migraciones financieras necesitan su propia coordinación, no dos autoridades competidoras.
Expand–migrate–contract conserva compatibilidad entre versiones: añadir capacidad de lectura o escritura, migrar de forma recuperable y retirar lo antiguo después de la ventana acordada. Volver a una imagen no deshace asientos ni una transformación destructiva. La decisión de rollback identifica qué puede restaurarse mediante código y qué necesita reconciliación de datos.
Los runbooks versionados pasan pruebas de precondiciones, dry run y límites de alcance. Se promueve la misma versión que se ensayó. El resultado incluye qué cambió, qué no pudo comprobarse y cómo reanudarlo; un código de salida exitoso no es la evidencia financiera final.
SLI, SLO y observabilidad del resultado
Se distinguen admisión, resultado, ciclo y reconciliación. Sus poblaciones, ventanas y condiciones de éxito son diferentes. Una respuesta rápida puede admitir trabajo que nunca termina; un pago registrado puede pertenecer a un ciclo todavía no confirmado. Los dashboards deben mostrar ambas dimensiones y el progreso entre ellas.
| Indicador | Definición y objetivo ilustrativo |
|---|---|
| Admisión | Fracción de solicitudes válidas aceptadas durablemente dentro del deadline de entrada; objetivo de 99.9% en treinta días. Los rechazos por saturación, incluido un 503, son eventos malos. |
| Resultado online | Fracción de pagos internos aceptados que obtiene una decisión durable correcta en cinco segundos; objetivo de 99.9% en treinta días. No se confunde aceptación con finalización. |
| Ciclo | Fracción de ciclos esperados confirmados y conciliados antes de su plazo; objetivo de 99% en una ventana de noventa días. La unidad es ciclo, no petición. |
| Reconciliación | Fracción de incertidumbres resueltas dentro de treinta minutos de disponibilidad del canal de consulta; objetivo de 99.5% en una ventana de treinta días, acompañado de edad real de todas las pendientes. |
Los números son elecciones del ejercicio. El SLO de ciclos es un objetivo operativo: su presupuesto de error no autoriza incumplir un cutoff contractual o regulatorio, que requiere excepción o incidente según la política. Una ventana sin muestras no se interpreta como éxito, y las poblaciones excluidas se reportan para evitar esconder impacto. Para cada ciclo se muestra además cercanía al cutoff, pasos pendientes y tiempo estimado de terminación con incertidumbre. La indisponibilidad del proveedor no borra la edad de una obligación ni elimina su dueño.
El presupuesto de error puede orientar releases o capacidad respecto a esos indicadores. Un error monetario no se consume como una cuota tolerable de disponibilidad. Un asiento desequilibrado, una salida duplicada o una autorización inválida activa contención e investigación de la invariante; no se normaliza porque el SLO mensual siga alto.
OpenTelemetry correlaciona métricas, logs y trazas a través de fronteras. Request ID, operation ID, attempt ID, event ID y cycle ID representan identidades distintas. Se conserva la identidad de negocio en registros durables aunque falle la exportación de telemetría. Sampling y ausencia de un span no prueban ausencia de una salida externa.
Datadog u Observe pueden organizar esas señales en un dashboard de impacto: operaciones aceptadas, decisiones finalizadas, pendientes por edad, discrepancias por moneda, progreso de ciclos, lag de fuentes, saturación de pools y estado del cerco. El operador debe poder pasar del síntoma a la población afectada y después a evidencia de autoridad. El producto concreto no crea esa relación automáticamente.
Se evita poner IDs por operación o participante en labels métricos sin cota. Los detalles quedan en logs o trazas con acceso, redacción y retención apropiados. Las dimensiones métricas pueden ser servicio, ruta normalizada, clase de resultado y entorno. El pipeline de señales tiene límites y degradación definidos para no detener pagos por un exportador caído.
Una alerta de burn rate compara la fracción mala observada con el presupuesto permitido por el SLO. Se combinan ventanas larga y corta para distinguir consumo sostenido de ruido; los umbrales se calibran con volumen, objetivo y urgencia. Una alerta de cutoff incorpora backlog, huecos y tiempos restantes de validación y confirmación, no únicamente CPU o un promedio optimista de throughput.
La severidad depende de impacto y urgencia. Una posible violación financiera o egress sin dueño exige contención inmediata; riesgo de perder un cierre requiere respuesta antes de su ventana. Los avisos se deduplican por incidente y flujo afectado, conservan un owner y enlazan su runbook. La observabilidad de invariantes permite cerrar el incidente cuando el resultado se comprobó, no sólo cuando desapareció la alerta.
La clasificación automática ejecuta reglas deterministas versionadas: una posible invariante monetaria rota o egress sin autoridad activa severidad crítica; el riesgo de perder cutoff asigna urgencia por tiempo restante y trabajo pendiente; los demás casos combinan población afectada y duración. Conserva entradas, versión y motivo. Un operador puede cambiar severidad con justificación auditada, sin borrar la decisión previa. Si el clasificador falla o faltan datos, mantiene la severidad previa o abre una evaluación conservadora con dueño y aviso; la ausencia de señal no reduce severidad. Su resultado enruta atención, no ejecuta movimientos financieros.
Runbooks deterministas y asistencia agentic
Un runbook empieza con contexto de entorno, población y versión. Comprueba precondiciones, identidad y permisos, muestra el alcance y aplica acciones acotadas. Registra referencias, resultado y postcondiciones. Python puede reconciliar manifests y evidencias; Java puede ejecutar tooling cercano al dominio; Shell puede componer diagnósticos con argumentos controlados. El lenguaje no reemplaza el contrato de la acción.
La automatización conserva idempotencia propia. Reanudar un job después de un timeout consulta la ejecución anterior antes de repetir un cambio. Un runbook de replay separa reconstrucción de vistas de despacho externo; otro puede detener admisión, reducir batch o recuperar una conexión. Las herramientas no aceptan SQL financiero arbitrario ni borran discrepancias para vaciar una cola.
Un runbook concreto de rotación de certificado toma execution_id, servicio, entorno y versión esperada. Sus precondiciones son permiso aprobado, material nuevo válido, CA y hostname esperados y capacidad para mantener la convivencia. La acción instala la nueva versión mediante rollout o reload controlado; cada paso registra progreso bajo ese ID. Las postcondiciones verifican cadena, hostname, nuevas conexiones y retirada acordada del material anterior, además de los permisos de negocio del participante. SNI no sustituye la verificación TLS y mTLS no amplía autorización. Si se interrumpe, consulta checkpoints y versión efectiva antes de continuar. La auditoría conserva actor, aprobaciones, referencias de versiones y pruebas, sin secretos. Un fallo detiene el siguiente paso y escala al dueño; este runbook no modifica asientos ni despacha dinero.
La IA puede reunir evidencia autorizada, ordenar una cronología, señalar contradicciones y proponer el siguiente paso. Su salida distingue observado, inferido y desconocido, y enlaza registros verificables. Una hipótesis del modelo no decide que un pago falló ni que corresponde reembolsarlo. Los datos sensibles se minimizan y el contexto conserva sus límites de acceso.
La ejecución se realiza mediante acciones deterministas con parámetros validados, permisos y alcance definidos. Cambios que afecten dinero, liderazgo, credenciales o recuperación necesitan las aprobaciones operativas previstas. No hay shell arbitrario autónomo ni autocobros para «probar» una reparación. La herramienta puede ofrecer dry run y evidencia; la decisión sobre una incertidumbre financiera sigue su protocolo.
El control incluye detener automatización ante precondiciones fallidas, presupuestos de reintentos y un interruptor operativo. Se mide cuánta ayuda fue útil, cuánto requirió corrección y qué evidencia falta. Automatizar un procedimiento no vuelve segura una acción cuya autoridad o resultado todavía no están establecidos.
Guardia, aprendizaje y coste del contrato
La guardia necesita ownership de servicio y de ciclo, contactos operativos internos y un mecanismo de escalamiento por impacto. El handoff transmite pendientes con identidad, edad, decisión conocida y próximo paso. La cobertura debe considerar las ventanas batch y del sistema externo; cerrar una jornada no cierra una obligación incierta.
El postmortem, sin culpabilizar, reconstruye condiciones y decisiones sin sustituir evidencia por intuiciones. Distingue causa, factores contribuyentes y límites de detección. Las acciones tienen dueño, prueba y plazo: fortalecer una precondición, añadir una señal de completitud o mejorar un ensayo de cerco es más concreto que pedir «más monitoreo».
El toil se mide por recurrencia, minutos de intervención y errores evitables. Un OKR puede reducir incertidumbres antiguas, tiempo de ensayo de recuperación o trabajo manual de conciliación, con una línea base comprobada. Se cuidan efectos secundarios: resolver más rápido no debe significar cerrar discrepancias sin evidencia. Logs, manifests, confirmaciones y artefactos se retienen según una política acordada y se prueba su recuperación.
Un job idempotente puede generar un paquete de evidencia de cumplimiento a partir de IDs, manifests, confirmaciones y versiones. Conserva procedencia, controles de completitud y acceso, y una identidad de ejecución vinculada a entradas versionadas para reanudar sin duplicar paquetes. Una fuente ausente se declara, no se inventa. Generar el paquete no certifica cumplimiento; su revisión y retención siguen la política aplicable.
El coste incluye réplicas, margen de capacidad, WAN, transferencia, observabilidad, almacenamiento de evidencia y entornos de prueba. Reducir retención puede eliminar replay; reducir una réplica puede cambiar el contrato del ACK. DR barato que no alcanza el objetivo bajo fallo no conserva el mismo servicio. Se comparan unidades y supuestos junto con la pérdida y duración observadas.
Ensayos que conectan diseño y operación
La verificación usa datos sintéticos, participantes de prueba y un canal externo seguro. Cada escenario declara estado inicial, fallo, invariante, evidencia y limpieza. Las pruebas se diseñan alrededor de ventanas difíciles; no se limita la validación a que un endpoint responda o un pod vuelva a arrancar.
Un ensayo pierde el ACK después del posting, repite la misma operación concurrentemente y comprueba un único movimiento válido. Otro mezcla payloads bajo la misma clave y verifica conflicto. Se prueba corrección autorizada sin reescribir journal, y una consulta de otro participante debe rechazarse aunque conozca el ID.
El relay cae entre publicación y checkpoint. El consumidor recibe duplicados y versiones invertidas; la proyección converge sin disparar egress. Una lease vence, otro worker reclama y el anterior reaparece. La prueba valida propiedad en el recurso y límites externos, no sólo la pantalla del coordinador.
El cierre batch recibe un evento tardío con timestamp anterior, un gap de secuencia y un archivo con totales que coinciden pese a registros ausentes. Debe impedir un sellado indebido o registrar una excepción explícita. Se pierde la respuesta del envío, se reciben confirmaciones parciales y se consulta por las mismas referencias. La conciliación detecta diferencias y no convierte un upload exitoso en ciclo liquidado.
Un ejercicio de failover mantiene vivo el sitio antiguo por otro camino. Se verifica el cerco antes de promover y se prueba que el egress anterior no continúa. Al retirar la réplica requerida, los ACKs no degradan silenciosamente. En DR asíncrono se mide historia perdida y se reconcilian los intentos originales antes de reactivar salidas.
La plataforma se prueba con pico online y batch simultáneos, saturación de pools, throttling y pérdida de red. Una rotación de Vault o certificados ocurre mientras hay conexiones y workers activos. La nueva versión convive con la anterior durante una migración y un fallo de telemetría no elimina el registro durable. El reporte conserva resultados y límites: un escenario no ensayado sigue siendo desconocido.
Cheat sheet pública
Antes de explicar o cambiar el sistema, comprobar:
- Qué operación y moneda se protegen, y quién tiene autoridad para decidir.
- Qué significa cada ACK y qué copias respaldan su durabilidad vigente.
- Qué identidad se conserva entre reintentos, publicaciones y envíos externos.
- Qué fuentes, membresía y evidencia permiten sellar el ciclo.
- Cómo se cercan escritor y egress, y qué permanece pausado durante recuperación.
- Qué población mide cada SLI, quién recibe la alerta y qué prueba cierra el incidente.
| Fallo | Respuesta | Garantía que se conserva | Prueba |
|---|---|---|---|
| ACK de pago perdido | Consultar o repetir identidad original. | Un movimiento local válido bajo su contrato. | Perder respuesta después del commit. |
| Envío externo incierto | Retener, consultar y reconciliar. | No inventar otra salida ni compensar a ciegas. | Perder respuesta con efecto externo confirmado. |
| Evento duplicado o replay | Deduplicar y recuperar vista. | Reconstrucción sin repetir dinero. | Cortar antes del checkpoint. |
| Gap antes del cutoff | Resolver fuente o registrar excepción. | Manifest sellado con membresía demostrable. | Omitir un registro con timestamp antiguo. |
| Writer antiguo aún vivo | Cercar efectivamente o pausar. | Una autoridad financiera válida. | Partición con camino alternativo al sitio viejo. |
| Réplica requerida perdida | Reconfigurar con catch-up probado o pausar ACKs. | Durabilidad explícita, sin degradación oculta. | Retirar el standby durante carga. |
| Credencial o certificado rotado | Convivencia, reload y verificación de retiro. | Acceso autorizado bajo el material vigente. | Conexiones nuevas y anteriores durante rotación. |
La explicación final debe poder seguir una instrucción, un evento, un intento externo y un ciclo sin confundir sus identidades. El criterio de éxito es conservar las invariantes y recuperar pendientes dentro de las fronteras comprobadas. La salud de procesos aporta señales a esa comprobación.
Referencias
Las referencias respaldan mecanismos concretos; la arquitectura y los objetivos de este caso son decisiones ilustrativas.
- PostgreSQL: transacciones, aislamiento y restricciones.
- PostgreSQL: replicación síncrona.
- AWS Builders’ Library: APIs idempotentes y timeouts, reintentos y jitter.
- Debezium: Outbox Event Router y Kafka: alcance de las garantías de entrega.
- OpenTelemetry: propagación de contexto y Prometheus: nombres y labels.