Operate Vs Apm Tools
APM tools (Dynatrace, Datadog, New Relic) monitorean infrastructure + traces + errors. Operate monitorea business process state (where is order #12345, what task está esperando, por qué está stuck). NO son equivalentes — son complementarios. Estrategia recomendada: APM para 80% del monitoring (infra, traces, alerts, performance) + minimal process inspector + CLI (~2K LOC vs 10K LOC) para el 20% que requiere business-process context. Reducción: 80% menos código que el spec previo, pero NO eliminar completamente — algunas operaciones requieren engine context que APM no tiene.
El malentendido fundamental¶
"Operate es para monitorear procesos"
Esta descripción es misleading. Operate hace dos cosas que la gente confunde:
| Aspecto | % de Operate | ¿Lo cubre APM? |
|---|---|---|
| System monitoring (TPS, latency, errors, infra) | ~30% | ✅ Mucho mejor |
| Business process state inspection + operations | ~70% | ❌ NO |
APM tools fueron diseñados para "trace de transacciones a través de servicios". Operate fue diseñado para "ver el estado de un workflow específico y operar sobre él".
Diferentes problemas, diferentes herramientas.
¿Qué hacen APM tools excelentemente?¶
Dynatrace, Datadog, New Relic, Grafana Cloud — todos cubren:
Infrastructure monitoring¶
- CPU, memory, disk, network del engine
- Database performance (queries, connections, locks)
- JVM/runtime metrics (GC, threads, heap)
- Cluster health
Application Performance Monitoring (APM)¶
- Distributed traces: client → gateway → engine → worker → external service
- Latency percentiles (p50, p90, p99)
- Error rates por endpoint
- Throughput (TPS, queue depth)
Logs aggregation¶
- Search across todos los services
- Pattern matching
- Correlation con traces
Alerts y anomaly detection¶
- Thresholds estáticos (TPS > X, latency > Y)
- ML-based anomaly detection (Dynatrace especialmente bueno)
- Multi-channel notifications
Dashboards¶
- Pre-built dashboards para stacks comunes
- Drag-and-drop custom dashboards
- TV mode para war rooms
Cost¶
- Dynatrace/Datadog: ~$15-100/host/mes
- Grafana Cloud: free tier generoso, paga por usage
- New Relic: ~$25-75/user/mes
¿Qué hace Operate que APM NO puede?¶
Aquí está el corazón del problema. APM tools no entienden BPMN.
Casos de uso únicos de Operate¶
1. "¿Dónde está el process instance #12345?"¶
APM puede decirte: "el último request a /v2/process-instances/12345 fue hace 5 min con 200 OK".
NO puede decirte: "el process instance está esperando en el user task 'Manager Approval' desde hace 2 días, asignado a Bob, con variable amount=50000".
Esto requiere business context — qué element está activo, qué scope, qué variables.
2. "Muéstrame todos los procesos stuck"¶
APM puede decirte: "100 instances completaron en la última hora".
NO puede decirte: "Hay 47 instances en estado INCIDENT, 23 esperando user tasks > 7 días, 12 con timer due date pasado pero no triggered (probable bug)".
Esto requiere queries específicas al state del engine.
3. "Resolve este incident"¶
APM puede alertarte cuando incident se crea. Tiene runbooks/playbooks.
NO puede ejecutar la acción de "resolve incident" — porque eso es una API call al engine que requiere business context (qué intentar reintentar, qué variables ajustar).
4. "Cancel estos 100 procesos por compliance"¶
APM no puede mutar state del engine. Es read-only de su perspectiva.
5. "BPMN visual con state overlay"¶
Mostrar el diagrama del proceso con highlighting de elementos activos requiere: - Knowing BPMN spec - Renderizar XML - Mapear element_instances a element_ids del modelo
APM no tiene contexto BPMN.
6. "Variables de esta instance"¶
Variables del proceso son un concept BPMN-specific. APM ve "row in some table" pero no entiende qué significa.
Tabla decisiva: qué cubre qué¶
| Pregunta | APM | Operate | Postgres directo |
|---|---|---|---|
| "¿Engine está vivo?" | ✅ Mejor | ⚠️ Básico | ⚠️ Health check |
| "¿Cuántos TPS?" | ✅ Mejor | ⚠️ Stat estática | ✅ SQL aggregate |
| "¿Latencia P99?" | ✅ Mejor | ❌ | ⚠️ Requiere event_log query |
| "¿Cuántos workers activos?" | ✅ Mejor | ❌ | ❌ |
| "¿DB connection pool full?" | ✅ Mejor | ❌ | ✅ pg_stat_activity |
| "¿Slow queries últimos 5 min?" | ✅ Mejor | ❌ | ✅ pg_stat_statements |
| "¿Errores del engine?" | ✅ Mejor | ❌ | ⚠️ Log scrape |
| "¿Memory leak en engine?" | ✅ Mejor | ❌ | ❌ |
| "¿Dónde está PI #12345?" | ❌ | ✅ | ✅ SQL query |
| "¿Variables de PI #X?" | ❌ | ✅ | ✅ SQL query |
| "¿Incidents activos?" | ⚠️ Solo count | ✅ | ✅ SQL query |
| "Resolve incident" | ❌ | ✅ | ⚠️ API call needed |
| "Cancel instance" | ❌ | ✅ | ⚠️ API call needed |
| "BPMN visual + state" | ❌ | ✅ | ❌ |
| "Tasks pendientes de Bob" | ❌ | ✅ Tasklist | ✅ SQL query |
| "Trace de un request" | ✅ Mejor | ❌ | ❌ |
| "Logs correlationados" | ✅ Mejor | ❌ | ❌ |
Conclusión visual: APM gana en system monitoring (top half). Operate/SQL gana en business state (bottom half).
La estrategia recomendada: hybrid¶
No construir Operate completo. En su lugar:
Capa 1 — APM (Dynatrace/Datadog/Grafana Cloud)¶
Cubre 80% del monitoring necesario:
flowchart TD
Dashboard[Dashboard de plataforma]
Dashboard --> M1[Engine TPS, latency, errors]
Dashboard --> M2[DB performance, connections]
Dashboard --> M3[Worker health]
Dashboard --> M4[Infra CPU, memory, disk]
Dashboard --> M5[Alerts y anomaly detection]
Inversión: setup ~1 semana, costo recurring de licencias.
Capa 2 — REST API + CLI ops¶
Para operaciones que requieren engine context, API + CLI son suficientes para devs/SREs:
# CLI ejemplo
mvp-cli process-instances list --state=INCIDENT --tenant=acme
mvp-cli process-instances get 12345
mvp-cli process-instances variables 12345
mvp-cli incidents list --since=1h
mvp-cli incidents resolve 9876
mvp-cli process-instances cancel 12345 --reason="duplicate order"
mvp-cli process-instances batch-cancel --filter='bpmnProcessId=order' --before=2025-01-01
Inversión: ~2-3 días para CLI completo si la REST API ya existe.
Capa 3 — Minimal "Process Inspector" web UI (~2K LOC)¶
Para business operators (que NO usan CLI), un UI muy mínimo:
┌──────────────────────────────────────────┐
│ Process Inspector │
├──────────────────────────────────────────┤
│ Search: [Process Instance Key/Business ID]│
│ │
│ Filters: │
│ □ State: [ACTIVE ▼] │
│ □ Process: [order-approval ▼] │
│ □ Has Incident: ☐ │
│ │
│ Results (50): │
│ ┌──────────────────────────────────────┐ │
│ │ 12345 | order-approval | ACTIVE │ │
│ │ Started: 2025-05-10 14:23 │ │
│ │ Current: Manager Approval (Bob) │ │
│ │ [View] [Variables] [Cancel] │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────┘
Features mínimas: - Search/list de instances - View detalle (current elements, variables como JSON tree) - Resolve incident (button + reason field) - Cancel instance (con confirmation)
Lo que SKIPamos vs Operate full: - ❌ BPMN visual viewer - ❌ Auto-refresh / real-time updates - ❌ Batch operations UI sofisticada - ❌ Tree view recursivo elaborado - ❌ History timeline detallada - ❌ Modification UI - ❌ Migration UI
Inversión: ~2K LOC, 1-2 semanas con 1 dev.
Stack concreto recomendado¶
flowchart TD
subgraph Users["USERS"]
SRE[SREs / DevOps]
BizOps[Business Ops]
Users3[End users in Tasklist]
end
SRE --> APM[APM tool buy]
BizOps --> Inspector[Process Inspector + CLI]
Users3 --> TasklistUI[Tasklist UI build full]
Inspector --> RestAPI[Engine REST API]
TasklistUI --> RestAPI
RestAPI --> EnginePG[(Engine + PostgreSQL)]
EnginePG -.->|metrics/traces/logs OpenTelemetry| APM
OpenTelemetry como abstracción¶
Crítico: el engine debe emitir metrics + traces + logs vía OpenTelemetry. Esto permite swap de APM tool:
# Engine setup
from opentelemetry import metrics, trace
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# Metrics
meter = metrics.get_meter("workflow-engine")
process_instances_created = meter.create_counter(
"process_instances.created",
description="Total process instances created"
)
processing_latency = meter.create_histogram(
"processing.latency",
description="Command processing latency",
unit="ms"
)
# Traces
tracer = trace.get_tracer("workflow-engine")
# En cada command processing
with tracer.start_as_current_span("process_command") as span:
span.set_attribute("command.intent", intent)
span.set_attribute("tenant.id", tenant_id)
span.set_attribute("process.definition.id", bpmn_process_id)
start = time.time()
result = process(command)
processing_latency.record(
(time.time() - start) * 1000,
attributes={"intent": intent, "tenant": tenant_id}
)
Configuración del exporter por env var:
# Dynatrace
OTEL_EXPORTER_OTLP_ENDPOINT=https://yourtenant.live.dynatrace.com/api/v2/otlp/v1
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Api-Token <token>"
# Datadog
OTEL_EXPORTER_OTLP_ENDPOINT=http://datadog-agent:4317
# Grafana Cloud
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod.grafana.net/otlp
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <base64-creds>"
# Honeycomb, New Relic, Lightstep, etc.
Beneficio: el usuario elige su APM. El MVP no se acopla a ningún vendor.
Métricas específicas del engine para exportar¶
Beyond standard system metrics, el engine debe emitir métricas business-specific:
| Métrica | Type | Atributos | Uso |
|---|---|---|---|
process_instances.created |
counter | tenant, bpmn_process_id | Throughput |
process_instances.completed |
counter | tenant, bpmn_process_id, outcome | Success rate |
process_instances.canceled |
counter | tenant, bpmn_process_id, reason | Cancellation patterns |
process_instances.duration |
histogram | tenant, bpmn_process_id | Time to complete |
process_instances.active.count |
gauge | tenant, bpmn_process_id | In-flight |
jobs.activated |
counter | tenant, job_type | Worker throughput |
jobs.completed |
counter | tenant, job_type, retries | Worker success |
jobs.failed |
counter | tenant, job_type, error_type | Worker errors |
jobs.duration |
histogram | tenant, job_type | Worker latency |
incidents.created |
counter | tenant, error_type, bpmn_process_id | Incident rate |
incidents.resolved |
counter | tenant, error_type | Resolution rate |
incidents.active.count |
gauge | tenant | Backlog |
commands.processed |
counter | intent, tenant | Engine load |
commands.processing.duration |
histogram | intent | Engine latency |
db.query.duration |
histogram | query_type | DB performance |
Con estas métricas, APM tool puede construir todos los dashboards que necesitas.
Dashboards predefinidos para Grafana¶
Para evitar que cada usuario reinvente dashboards, el MVP incluye dashboards Grafana exportados (JSON files) en el repo:
mvp-monitoring/
├── dashboards/
│ ├── platform-health.json (engine TPS, latency, errors)
│ ├── process-throughput.json (instances by process)
│ ├── worker-performance.json (jobs metrics)
│ ├── incident-tracking.json (incident rate, resolution)
│ └── postgres-performance.json (DB metrics)
├── alerts/
│ └── recommended-alerts.yaml (Prometheus alertmanager)
└── README.md
Usuario importa el JSON a su Grafana → tiene monitoring funcional inmediato.
Comparison: Build Operate vs Hybrid approach¶
| Aspecto | Build Operate full | Hybrid (APM + Inspector + CLI) |
|---|---|---|
| LOC inicial | ~10K | ~2K |
| Tiempo desarrollo | 3 sprints (~6 sem) | 1-2 sem |
| Cost recurring | $0 (build it) | $15-100/host/mes (APM) |
| Monitoring quality | Limited (Camunda style) | Best-in-class (Dynatrace ML) |
| Anomaly detection | NO | YES (APM features) |
| Distributed tracing | NO | YES (APM) |
| Process state queries | YES | YES (via Inspector + CLI) |
| Incident resolution | YES | YES (via Inspector) |
| Batch operations | YES (UI) | YES (CLI) |
| BPMN visual | YES | NO (puedes verlo en Modeler externo) |
| Real-time auto-refresh | YES | NO (manual refresh) |
| Multi-tenant capable | YES (built-in) | YES (via APM tags) |
| Mobile friendly | Maybe | Yes (most APMs) |
| Total ownership | Tu equipo | Vendor responsibility |
Cost analysis¶
Para un equipo de 3 devs + 1 platform engineer durante 1 año:
Build Operate full:
Dev time: 3 sprints × 2 devs = ~6 dev-weeks = ~$30K
Ongoing maintenance: ~15% time of 1 dev = ~$25K/año
Total año 1: ~$55K
Total año 2+: ~$25K/año
Hybrid approach:
Dev time: 2 weeks × 1 dev = ~$5K
APM cost (5 hosts × $20/host × 12 months): ~$1.2K/año
Total año 1: ~$6.2K
Total año 2+: ~$1.2K/año + minor maintenance
Saving: ~$48K año 1, ~$24K/año recurring
Even at higher APM costs (Dynatrace enterprise), the hybrid wins by 5-10x.
Cuándo SÍ build Operate full¶
Hay casos donde APM no es suficiente:
Caso 1: Compliance que requiere airgap¶
Si tu industria requiere que NO datos salgan a un SaaS APM (banking, defense, government): - Self-hosted Grafana es opción (zero data egress) - Pero si Grafana no es suficiente UX para business operators - Entonces SÍ build Operate
Caso 2: BPMN visual es requirement crítico¶
Si los users necesitan ver el BPMN diagram con state highlighted constantemente: - APM no tiene esto - Inspector mínimo tampoco - Build BPMN viewer custom (~3K LOC adicional, bpmn-js + state mapping)
Caso 3: Volume tan alto que APM cost prohibitivo¶
A escala extrema (millones de instances, miles de hosts): - APM costs pueden volverse caros - Build interno tiene economics diferentes - Pero: probablemente también necesitas la sofisticación de Operate
Caso 4: White-label para tus clientes¶
Si vendes tu plataforma como SaaS y necesitas dashboard branded: - Difícil rebrand APM tools - Build interno es necesario
Para 95% de casos, ninguno de estos aplica. Hybrid gana.
El sweet spot: minimal Process Inspector¶
Si decides ir hybrid pero quieres algo más que CLI, este es el mínimo viable:
Features (todo en 1 página)¶
┌─────────────────────────────────────────────┐
│ 🔍 [Search: instance key / business ID] │
│ │
│ Quick filters: │
│ [Active] [Incidents] [Recent (24h)] │
│ │
│ Custom filter: │
│ Process: [__________ ▼] │
│ State: [Active ▼] │
│ Since: [__________] │
│ Until: [__________] │
│ │
│ Results (showing 1-50 of 247): │
│ ┌────────────────────────────────────────┐ │
│ │ #12345 | order-approval | ACTIVE │ │
│ │ Business ID: ORD-789 │ │
│ │ Started: 2 hours ago │ │
│ │ Current: Manager Approval (assigned │ │
│ │ to bob@acme.com) │ │
│ │ [Details] [Variables] [Cancel] │ │
│ ├────────────────────────────────────────┤ │
│ │ #12346 | order-approval | INCIDENT │ │
│ │ ... │ │
│ └────────────────────────────────────────┘ │
│ [< Prev] [Next >] │
└─────────────────────────────────────────────┘
Acciones disponibles¶
Modal "Details":
┌──────────────────────────────────────────┐
│ Process Instance #12345 │
├──────────────────────────────────────────┤
│ Process: order-approval (v3) │
│ State: ACTIVE │
│ Started: 2025-05-10 14:23:11 UTC │
│ Tenant: acme │
│ Business ID: ORD-789 │
│ │
│ Current elements: │
│ • Manager Approval (USER_TASK) │
│ Assigned: bob@acme.com │
│ Active since: 2h 15m │
│ │
│ [View Variables] [View History] [Cancel] │
└──────────────────────────────────────────┘
Modal "Variables":
┌──────────────────────────────────────────┐
│ Variables of PI #12345 │
├──────────────────────────────────────────┤
│ { │
│ "orderId": "ORD-789", │
│ "amount": 50000, │
│ "customer": { │
│ "id": "CUST-001", │
│ "email": "alice@example.com" │
│ }, │
│ "approvers": ["bob@acme.com"] │
│ } │
│ │
│ [Copy JSON] [Edit] [Close] │
└──────────────────────────────────────────┘
Eso es todo. 1 search page + 2 modals. ~2K LOC.
Stack: - React + Tailwind: ~500 LOC - API client + state: ~300 LOC - 2 modals: ~600 LOC - Search/filter logic: ~400 LOC - Auth integration: ~200 LOC - Total: ~2K LOC
Lo que CLI cubre para el resto¶
CLI maneja casos avanzados que no necesitan UI: - Batch operations - Migrations - Advanced filters - Scripting/automation - CI/CD integration
# Power user workflow
mvp-cli process-instances list \
--state=INCIDENT \
--process=order-approval \
--since=24h \
--format=json | \
jq '.[] | select(.incidentType == "JOB_NO_RETRIES")' | \
jq -r '.processInstanceKey' | \
xargs -I {} mvp-cli incidents resolve --pi {}
DevOps/SREs aman esto. Business users usan el UI.
Resumen ejecutivo¶
Recomendación: hybrid approach¶
| Capa | Tool | Inversión | Cubre |
|---|---|---|---|
| System monitoring | APM (Dynatrace/Datadog/Grafana) | $1K-10K/año + setup | Infra, traces, logs, alerts |
| CLI operations | Build (~500 LOC) | 2-3 días | Power users, scripting, batch ops |
| Process Inspector UI | Build (~2K LOC) | 1-2 semanas | Business operators, basic search |
| Tasklist | Build (~8K LOC) | 3 sprints | End users (necessary, no replacement) |
Total: ~10.5K LOC + APM tool vs ~18K LOC building Operate + Tasklist completos.
Saving: ~8K LOC + mejor monitoring + lower maintenance burden.
La pregunta clave¶
"¿Mis usuarios necesitan BPMN visual con state overlay constantly?"
- NO → hybrid approach (recomendado)
- YES → build Process Inspector con bpmn-js viewer (~3K LOC adicional = 5K total)
- YES, también modification y migration → build Operate full (~10K LOC)
Lo que NO cambia¶
- Tasklist: SÍ build completo. No hay APM equivalent. User tasks son core feature.
- Engine REST API: SÍ build completo. APM no es write. Inspector y CLI consumen esta API.
- OpenTelemetry export: SÍ build desde día 1. Vendor-agnostic, plug & play APM.
Resultado final¶
| Componente | Decisión revisada | LOC |
|---|---|---|
| ~~Operate full~~ | SKIP | ~~10K~~ |
| Process Inspector minimal | BUILD | 2K |
| CLI ops | BUILD | 0.5K |
| OpenTelemetry export | BUILD | 0.5K |
| Tasklist | BUILD (sin cambio) | 8K |
| APM tool | BUY | $1K-10K/año |
| Grafana dashboards | SHIP (JSON files) | 0K |
Total reducción vs spec previo: ~7.5K LOC (de 18K a 11K).
Esta es probablemente la mejor decisión arquitectónica del MVP: usar tools especializados para lo que hacen bien (APM para monitoring, BPMN engine para business state) en vez de construir un híbrido mediocre.
Referencias¶
- analysis/webapps-architecture-mvp — Estrategia overall (esta página la revisa)
- analysis/operate-tasklist-mvp-detailed — Spec previo de Operate full (deprecated en favor de hybrid)
- entities/operate — Operate de Camunda como reference
- OpenTelemetry: https://opentelemetry.io
- Grafana: https://grafana.com
- Dynatrace: https://www.dynatrace.com
- Datadog: https://www.datadoghq.com
- New Relic: https://newrelic.com