> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Operación de Streaming Hub

> Despliega Streaming Hub con Helm en BYOC, ejecuta migraciones fuera de banda, conecta las sondas de liveness y readiness, define la configuración esencial y observa el hub por OTLP.

Esta página es para operadores que ejecutan Streaming Hub en su propia infraestructura (BYOC). Cubre el despliegue, la configuración que importa, el contrato de salud y apagado, y cómo observar el servicio.

## Despliegue con Helm

***

Streaming Hub se entrega como un Helm chart dedicado, `streaming-hub-helm`, separado de cualquier otro chart de producto de Lerian. El chart ejecuta el hub en una de dos formas:

* **`all`**: un solo deployment que ejecuta cada worker de segundo plano. Es la forma predeterminada y la más simple de operar.
* **`split`**: deployments de **ingesta** y de **entrega** separados que escalan de forma independiente: las réplicas de ingesta comparten un grupo de consumidores de Kafka, mientras que las réplicas de entrega trabajan los trabajos de entrega desde Postgres.

La forma split se controla por proceso con `STREAMING_HUB_ROLE` (`all` | `ingest` | `delivery`). El rol controla **qué workers de segundo plano corren y qué clientes de Kafka se conectan**. **No** controla qué rutas HTTP se montan. Cada rol sirve la API completa del plano de control y, sobre todo, el endpoint `/readyz` del que dependen tu orquestador y la recolección de métricas. Hay una sola imagen y un solo binario. El rol es una entrada del despliegue, no de la compilación.

## Ejecución de migraciones de base de datos

***

Streaming Hub usa una sola base de datos PostgreSQL que le pertenece, y **nunca se migra a sí mismo**. Las migraciones de esquema corren **fuera de banda**. Un paso de migración aparte (por ejemplo, un hook PreSync de ArgoCD) aplica las migraciones versionadas antes de que el hub arranque. En el arranque el hub solo *verifica* que la versión de esquema que espera esté presente. Nunca ejecuta una migración como efecto secundario de arrancar.

El hub sí aprovisiona por adelantado sus propias particiones de tabla semanales, como una tarea rutinaria de segundo plano. Eso cuenta como mantenimiento interno, no como una migración de esquema. No necesita acción del operador, mientras el cron de particiones siga corriendo.

## Salud y apagado ordenado

***

Streaming Hub expone dos endpoints de sonda distintos. Conecta cada uno a la sonda de Kubernetes correspondiente:

| Endpoint   | Sonda     | Comportamiento                                                                                                                                                                                                                                            |
| ---------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/healthz` | Liveness  | Devuelve `200` sin condiciones una vez que el proceso está sirviendo, con independencia de la salud de Postgres, de Kafka o del consumidor de ingesta de aplicación. Una falla de liveness reinicia el pod, así que no debe depender de las dependencias. |
| `/readyz`  | Readiness | Reúne el conjunto completo de sondas del rol. `Healthy` o `Degraded` → `200` (se mantiene en rotación); `Down` → `503` (se saca de rotación). Una réplica `Degraded` sigue sirviendo.                                                                     |

`/readyz` distingue dos clases de falla. Una falla de **sonda de runtime** (Postgres inalcanzable, consumidor muerto) deja la réplica en **Down** y fuera de rotación. Un **degradador** (latencia elevada, lag del consumidor, un búfer de partición escaso) fija la réplica en **Degraded** pero la mantiene sirviendo. Se recomienda que una réplica con problemas no rechace tráfico. El conjunto de sondas conoce el rol. La ausencia de un consumidor de ingesta nunca deja sin listo a un pod con rol de entrega.

Ante un `SIGTERM` el hub drena de forma ordenada. **Primero** cambia `/readyz` a `NotReady`, antes de dejar de servir. Luego espera una ventana pre-stop acotada, para que el orquestador pueda sacar el pod del servicio antes del cierre de conexiones. El endpoint `/healthz` se mantiene en `200` todo el tiempo, así que el orquestador no mata el pod a mitad del drenaje. Luego desmonta en un orden seguro para las dependencias (HTTP, después el consumidor, después el dispatcher, después las apps de segundo plano, después los clientes de Kafka, después el pool y después la telemetría).

<Warning>
  Define el `terminationGracePeriodSeconds` del deployment en el techo de drenaje derivado del hub para tu `STREAMING_HUB_SHUTDOWN_TIMEOUT`, o por encima, no en un número mágico fijo. Con el timeout de apagado predeterminado de 30 segundos el techo es de unos **80 segundos**. Ese total es la ventana pre-stop de 5 segundos más el propio timeout de apagado. También incluye un tramo de drenaje del dispatcher de `min(timeout, 55s)` en el peor caso y un margen fijo de desmontaje para los componentes restantes.

  Un período de gracia por debajo del techo arriesga un `SIGKILL` de una réplica que todavía está drenando. Eso es seguro para la corrección, pero pierde el drenaje limpio. El hub recupera y reentrega los trabajos en curso, y el consumidor los deduplica.
</Warning>

`/version` (identidad de la compilación) y `/runtime` (una instantánea barata del runtime de Go) completan la superficie operativa sin autenticación para el triaje de incidentes.

## Configuración esencial

***

Streaming Hub lee su configuración de variables de entorno `STREAMING_HUB_*`, además de las variables compartidas `MULTI_TENANT_*`, `PLUGIN_AUTH_*` y `OTEL_*` y de `ENV_NAME`, sin prefijo. El inventario completo, con cada valor predeterminado, vive en la referencia de entorno del servicio. Las variables que defines con más frecuencia:

| Variable                               | Predeterminado                           | Propósito                                                                                                                                                                                                                                                                                                                                                                                                              |
| -------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `STREAMING_HUB_ENV`                    | `local`                                  | Entorno de despliegue (`local` \| `staging` \| `production`). Impulsa el control de seguridad de producción que rechaza los flags de bypass de desarrollo.                                                                                                                                                                                                                                                             |
| `STREAMING_HUB_ROLE`                   | `all`                                    | Porción desplegable: `all` \| `ingest` \| `delivery`. Controla workers y clientes de Kafka, nunca rutas.                                                                                                                                                                                                                                                                                                               |
| `STREAMING_HUB_HTTP_LISTEN_ADDR`       | `:8080`                                  | La única dirección de escucha del plano de control.                                                                                                                                                                                                                                                                                                                                                                    |
| `STREAMING_HUB_POSTGRES_DSN`           | *(obligatorio)*                          | El DSN de PostgreSQL que pertenece al hub. El arranque falla si está vacío.                                                                                                                                                                                                                                                                                                                                            |
| `STREAMING_HUB_KAFKA_BROKERS`          | *(vacío)*                                | Lista de brokers de bootstrap para el stream interno.                                                                                                                                                                                                                                                                                                                                                                  |
| `STREAMING_HUB_TENANT_ID`              | `default`                                | El id de tenant de BYOC. Lee la advertencia de abajo antes de cambiarlo.                                                                                                                                                                                                                                                                                                                                               |
| `STREAMING_HUB_MANIFEST_SOURCES`       | *(vacío)*                                | URLs base de productores separadas por comas cuyos manifiestos llenan el catálogo en modo BYOC. Las URLs inválidas hacen fallar el arranque. Esta variable está prohibida en modo multi-tenant.                                                                                                                                                                                                                        |
| `STREAMING_HUB_MANIFEST_CLIENT_ID`     | *(vacío)*                                | Id de cliente opcional que se usa para traer los manifiestos de productores BYOC. Defínelo junto con `STREAMING_HUB_MANIFEST_CLIENT_SECRET`; dejar los dos vacíos usa descargas anónimas.                                                                                                                                                                                                                              |
| `STREAMING_HUB_MANIFEST_CLIENT_SECRET` | *(vacío)*                                | Secreto de cliente opcional para las descargas de manifiestos. Definir una sola credencial de manifiesto hace fallar el arranque.                                                                                                                                                                                                                                                                                      |
| `STREAMING_HUB_KEK_SOURCE`             | `env`                                    | Proveedor de la clave de cifrado de claves (`env` \| `secretsmanager`).                                                                                                                                                                                                                                                                                                                                                |
| `STREAMING_HUB_KEK_REF`                | *(vacío)*                                | El **nombre** de la variable de entorno que contiene el material del KEK, nunca el material en sí.                                                                                                                                                                                                                                                                                                                     |
| `PLUGIN_AUTH_ADDRESS`                  | *(predeterminado de plugin-auth)*        | La URL base del punto de decisión de plugin-auth para la autorización del plano de control.                                                                                                                                                                                                                                                                                                                            |
| `PLUGIN_AUTH_ENABLED`                  | `true`                                   | Interruptor maestro de autenticación. `false` es un bypass local, **rechazado en producción**.                                                                                                                                                                                                                                                                                                                         |
| `STREAMING_HUB_AUTODISABLE_ENABLED`    | `true`                                   | Interruptor de apagado para la desactivación automática de destinos rotos.                                                                                                                                                                                                                                                                                                                                             |
| `STREAMING_HUB_SHUTDOWN_TIMEOUT`       | `30s`                                    | Ventana de drenaje ordenado. La ventana pre-stop más `min(value, 55s)` debe quedar estrictamente por debajo del lease de 60 segundos del dispatcher, o el arranque falla en cerrado.                                                                                                                                                                                                                                   |
| `MULTI_TENANT_ENABLED`                 | `false`                                  | `false` es BYOC de un solo tenant; `true` usa Tenant Manager para el listado de tenants activos, mientras cada réplica con capacidad de ingesta corre un consumidor de Kafka de aplicación con `STREAMING_HUB_KAFKA_*`.                                                                                                                                                                                                |
| `MULTI_TENANT_URL`                     | *(obligatorio en modo multi-tenant)*     | URL base del servicio Tenant Manager que se usa para el listado inicial y la actualización periódica.                                                                                                                                                                                                                                                                                                                  |
| `MULTI_TENANT_SERVICE_API_KEY`         | *(obligatorio en modo multi-tenant)*     | Credencial de servicio que se usa para autenticar las solicitudes a Tenant Manager.                                                                                                                                                                                                                                                                                                                                    |
| `MULTI_TENANT_REDIS_HOST`              | *(vacío; opcional en modo multi-tenant)* | Endpoint opcional de Redis para actualizaciones del ciclo de vida de tenants casi en tiempo real. Cuando no se define, el listener no arranca. La actualización periódica de Tenant Manager igual converge el listado; en un pod de solo entrega, el listado queda fijo hasta el reinicio. Configura la contraseña, la base de datos y los ajustes de TLS correspondientes cuando tu despliegue de Redis los requiera. |
| `ENV_NAME`                             | *(obligatorio en modo multi-tenant)*     | Segmento de entorno en la ruta de Secrets Manager `tenants/{ENV_NAME}/...` para las credenciales M2M por tenant de los manifiestos de productores.                                                                                                                                                                                                                                                                     |
| `STREAMING_HUB_AWS_HUB_PRINCIPAL_ARN`  | *(vacío)*                                | El principal de IAM público del hub incrustado en los artefactos de configuración de AWS. Obligatorio para los sinks de AWS.                                                                                                                                                                                                                                                                                           |
| `STREAMING_HUB_AWS_SETUP_TEMPLATE_URL` | *(vacío)*                                | La URL pública de la plantilla de CloudFormation para el enlace de creación rápida de AWS.                                                                                                                                                                                                                                                                                                                             |
| `OTEL_EXPORTER_OTLP_ENDPOINT`          | *(vacío)*                                | El endpoint del colector OTLP al que se exporta la telemetría (sin el prefijo `STREAMING_HUB_`).                                                                                                                                                                                                                                                                                                                       |

Quitar una URL de `STREAMING_HUB_MANIFEST_SOURCES` detiene las actualizaciones futuras de ese productor, pero conserva sus últimas filas de catálogo válidas conocidas. La actualización de manifiestos es descubrimiento del plano de control y nada más. Una caída de un productor no bloquea la ingesta de eventos ni la coincidencia de entregas.

Los **valores** de los secretos nunca van en configuración versionada. Referencias el KEK por el *nombre* de la variable de entorno en la que la capa de despliegue lo inyecta (`STREAMING_HUB_KEK_REF`). El hub lee el material de esa variable nombrada y nunca lo registra en logs. El material de SASL y TLS de Kafka en el nivel del despliegue, la clave de API de servicio de Tenant Manager y las credenciales de Redis deben venir de tu almacén de secretos. Las credenciales M2M por tenant para el descubrimiento de manifiestos de productores se quedan en Secrets Manager.

<Warning>
  **`STREAMING_HUB_TENANT_ID` define el tenant del plano de control en BYOC.** La ingesta acepta cualquier `ce-tenantid` no vacío. El hub persiste un tenant distinto, pero ese tenant no puede coincidir con suscripciones que pertenecen a este tenant de BYOC. Si defines un valor distinto, las suscripciones deben usar ese tenant. De lo contrario la ingesta tiene éxito, pero la entrega queda vacía. Un valor distinto del predeterminado emite una advertencia de arranque. Hazle caso.
</Warning>

## Análisis forense de la DLQ

***

`GET /admin/dlq` es la superficie forense del operador para las observaciones de dead-letter. Es **entre tenants por diseño**. El ámbito de admin de lib-auth lo controla, **no** lleva capa de tenant y devuelve registros de todos los tenants. Por eso no forma parte de la API `/v1` para clientes.

Las observaciones de dead-letter que lee son **solo para observabilidad**. Vienen de los temas de dead-letter de productores upstream, y el hub nunca las reentrega. Úsalo para investigar por qué fallaron registros upstream. No los reproduce.

## Conciliador de temas

***

El conciliador de temas es un detector de desviaciones **de solo lectura**, habilitado de forma predeterminada (`STREAMING_HUB_RECONCILER_ENABLED`). En cada pasada compara los temas vivos del broker, el catálogo de eventos y los destinos distintos de las suscripciones. Marca tres clases de desviación:

* **temas fantasma**: un tema seguido sin entrada en el catálogo.
* **suscripciones muertas**: un tipo de evento y major suscrito sin entrada viva en el catálogo.
* incumplimientos de **lag frente a retención**.

**Detecta, nunca corrige**. Emite gauges de solo conteo y logs estructurados, y no escribe estado en el broker ni en la base de datos. Cuando está deshabilitado, no lanza ninguna goroutine ni conecta ningún cliente de admin, así que el camino deshabilitado no cuesta nada. Un conciliador deshabilitado pierde una alarma operativa, pero nunca afecta la entrega.

## Observabilidad

***

Streaming Hub exporta sus métricas, trazas y logs por **OTLP** (lib-observability), apuntando al colector de `OTEL_EXPORTER_OTLP_ENDPOINT`. Ahí es donde viven las métricas `streaming_hub_*` reales.

<Note>
  El endpoint `/metrics` está **casi vacío por diseño**: sirve solo el gauge estático `streaming_hub_build_info`. Recoge las métricas reales del hub desde tu colector OTLP, no desde `/metrics`.
</Note>

La identidad de tenant nunca es una etiqueta de métrica. Vive en atributos de span y en campos de log, así que la cardinalidad de las métricas se mantiene acotada sin importar cuántos tenants sirva un despliegue.

## Próximos pasos

***

<CardGroup cols={2}>
  <Card title="Cómo funciona Streaming Hub" icon="diagram-project" href="/es/platform/streaming-hub/how-streaming-hub-works">
    Los detalles internos de entrega detrás de las superficies operativas de arriba.
  </Card>

  <Card title="Gestión de suscripciones" icon="gear" href="/es/platform/streaming-hub/managing-subscriptions">
    Las operaciones del plano de control que usan tus tenants.
  </Card>
</CardGroup>
