Volver

Ingeniería Xeni · Plataforma

Falcon: El Chasis Detrás de Cada Servicio de Xeni

Maha Nachiappan & Jayganesh BPlataforma Xeni·9 min de lectura·Agosto 2026
Plataforma e InfraestructuraGoFrameworkPlataformaArquitectura

Antes de que un microservicio pueda hacer algo útil, tiene que hacer las mismas docena de cosas que ya hace cualquier otro servicio: leer configuración, autenticar al llamador, acceder a una base de datos, cachear un resultado, publicar un evento, obtener un secreto, emitir métricas y logs. Escrito una vez por servicio, esa plomería se duplica, se desvía y envejece mal.

La respuesta de Xeni es Falcon — un framework interno en Go sobre el que se construye cada servicio backend. Falcon se encarga de la infraestructura para que cada servicio se encargue solo de su dominio. Es la razón por la que un equipo pequeño puede operar muchos servicios sin levantar un grupo de plataforma detrás de cada uno.

Esta publicación es un recorrido por lo que hace Falcon, cómo está armado y las compensaciones que asumimos para construir una base compartida en lugar de muchas a medida.

Una nota sobre el nombre

Falcon aquí es el framework interno de Go de Xeni — no el proyecto open source en Python no relacionado con el mismo nombre. Todo lo que sigue es Go.

El costo de no tener uno

Escrito una vez por servicio, esa misma infraestructura se duplica y silenciosamente se desvía. Sin un chasis compartido, estos costos se repiten en cada servicio:

Sin un chasis compartidoQué ocurre
Boilerplate repetidoCada equipo reimplementa enrutamiento, config, logging, auth, pools de BD, caché y métricas — semanas de trabajo antes de que el primer endpoint de negocio salga a producción.
Seguridad inconsistenteLos servicios validan tokens, resuelven tenants y enmascaran PII de forma diferente, y las brechas salen a la luz en auditorías y revisiones de incidentes.
Deriva operacionalLogs, etiquetas de métricas, sobres de error e IDs de correlación difieren por servicio, por lo que depurar fallos entre servicios se vuelve lento y frágil.
Dependencia de proveedorLlamadas directas a SDK de AWS o GCP en código de producto hacen que las migraciones de nube o mensajería sean costosas y riesgosas.
Incorporación lentaLos nuevos ingenieros aprenden una forma de stack diferente en cada repo en lugar de un contrato de plataforma único.
Fricción de escalaConnection pooling, bloqueos distribuidos, reintentos y eventing se reinventan — o se omiten bajo presión de entrega.

Falcon existe para que los equipos de producto escriban lógica de dominio, mientras la plataforma se encarga de la corrección de infraestructura una sola vez — versionada, probada y reutilizada en todas partes.

Un chasis, cada servicio

La plataforma no es ni un monolito ni un conjunto disperso de apps no relacionadas. Cada vertical de producto y cada servicio de soporte — supply, payments, identity, AI — es un servicio separado construido sobre el mismo chasis Falcon. Los nuevos productos y capacidades son aditivos: heredan la base en lugar de reconstruirla.

Capa de interfaz

Web

API

MCP

SDK

Verticales de producto

Hoteles

Vuelos

Autos

Actividades

Resorts

Paquetes

Servicios

Suministro y descubrimiento

Servicios de proveedores

Servicios de agregadores

Búsqueda y catálogo

Auto Complete

Recomendaciones

Ofertas

Pagos y liquidación

Servicio de pago FIAT

Servicio de pago Crypto

Servicio de liquidación

Agentes de pago

Plataforma e IA

IDAM — identidad y confianza

Servicio backend de IA

Jobs de Temporal

Notificaciones

FALCON

chasis Go compartido · config · auth · data · cache · streaming · secrets · observability

Plano de datos y streamingPostgres · Redis · OpenSearch · Kafka

Figura 1. Una capa de interfaz — Web, API, MCP y SDK — da frente a seis verticales de producto (hoteles, vuelos, autos, actividades, resorts, paquetes); supply, payments y servicios de plataforma/AI se sitúan debajo, y todo corre sobre el chasis Falcon encima de un plano compartido de datos y streaming.

Lo mismo se cumple en toda la flota. Más allá de los productos, la plataforma misma corre sobre Falcon — identity, configuration, accounts, reporting, operator tooling, payments, subscriptions, data migration, notifications, AI — y, para cada vertical, servicios de agregación que unifican docenas de servicios conector de proveedores. Cada uno de ellos es un servicio Falcon sobre el mismo chasis:

Servicios sobre Falcon

Identity (IDAM)

authN · authZ · trust

Config Management

config de runtime central

Account Service

orgs · accounts · users

Reporting Service

analytics e informes

Customer Admin

consola Command Center

Multi-Tenant Mgmt

herramientas de operador Xeni

Notification Service

email · SMS · push

AI Backend

agentes y servicio de modelos

Payment Service

fiat y crypto · liquidación

Data Migration

esquemas y movimientos de datos

Subscription Service

planes recurrentes y facturación

Aggregation Services

tie dozens of connectors — each a service · per vertical

FALCON

chasis Go compartido · config · auth · data · cache · streaming · secrets · observability

Plano de datos y streamingPostgres · Redis · OpenSearch · Kafka

Figura 2. La flota de servicios de Xeni sobre Falcon — servicios de plataforma y comercio (identity, config, accounts, reporting, admin, tenant management, notifications, AI, payments, subscriptions, data migration), y, para cada vertical, servicios de agregación que unen docenas de servicios conector de proveedores — cada uno un servicio Falcon por derecho propio.

Una llamada, y la plomería está hecha

Un nuevo servicio Falcon comienza con casi ningún código de infraestructura. Creas el servidor, registras las rutas y le entregas el control al framework:

go
// main.go — create the server, register the routes, hand off to the framework.
func main() {
    falcon := server.NewFalcon()
    routers.AddRouters(falcon)
    falcon.Fly()
}

// routers.go — one line per endpoint:
//   method, API version, path, allowed roles, request body, handler
func AddRouters(falcon *server.Falcon) {
    falcon.Add(
        routes.POST, routes.V2, "/bookings",
        []routes.Role{constants.ScopeAdmin},
        &model.BookingRequest{}, handlers.Booking,
    )
    // ...more routes...
}

Las rutas viven en un routers.go — un solo falcon.Add por endpoint, declarando el método, versión de API, ruta, los roles permitidos para llamarlo, el cuerpo de solicitud a vincular y validar, y el handler. main.go casi no hace nada: crear el servidor, registrar las rutas y volar.

Cada handler tiene la misma firma — func(ctx) (interface{}, *APIError) — para que el framework pueda centralizar serialización, mapeo de error a HTTP, recuperación de pánico, propagación de request-id y correlación, y negociación de contenido. Todo lo que un handler necesita — configuración, clientes de base de datos y caché, clientes salientes — cuelga del context de la solicitud, recuperado con helpers server.Get*(ctx) en lugar de pasarse a mano. El handler en sí no hace el trabajo inline; compone la solicitud a partir de workers pequeños e independientes — donde vive la lógica de dominio real.

Desde el lado del ingeniero de producto, eso convierte una nueva funcionalidad en una lista de verificación corta y predecible:

  1. 01Define el modelo de solicitud — Falcon lo vincula y valida desde el cuerpo.
  2. 02Agrega una línea de ruta en routers.go — método, versión, ruta, roles, cuerpo, handler.
  3. 03Escribe un handler delgado que compone un flujo de trabajo.
  4. 04Escribe los workers — unidades pequeñas e independientes de lógica de dominio (un validator, una policy, los pasos).
  5. 05Conecta cualquier dependencia nueva — una base de datos, caché o servicio saliente — a través de config, no de código.

Todo lo demás — autenticación, autorización, logging estructurado, métricas, tracing, IDs de correlación, sobres de error, serialización, recuperación de pánico, y endpoints de health / metrics — el framework ya lo maneja. Esa es la habilitación: un ingeniero dedica su tiempo a la funcionalidad, no a la plomería.

El trabajo en segundo plano es igual de ligero: falcon.AddBatch(name, fn) registra un job de inicio que corre en su propia goroutine — el mismo cableado, sin una ruta HTTP.

La config es el cableado

Falcon es impulsado por configuración. Casi toda capacidad — una base de datos, una caché, un cliente HTTP saliente, un stream, un proveedor de nube — se instancia desde un group de config con nombre y un tipo declarado. Agregar una dependencia downstream es un cambio de configuración, no código nuevo.

La configuración es un formato plano de claves con puntos — <service>.<group>.<key>=<value> — cargado ya sea desde un archivo local o desde un servicio de config central (autenticado con un token de servicio a servicio). Falcon descubre groups por ese segmento del medio, que es cómo un solo servicio puede conectar varias bases de datos tipadas (por ejemplo groups separados tenantdb y coredb), múltiples streams o muchos clientes salientes puramente a través de config. Los getters tipados devuelven valores con defaults sensatos, de modo que el mismo binario se comporta correctamente en cada entorno — y los operadores pueden incluso cambiar la verbosidad de logs en tiempo de ejecución con PUT /loglevel/:level, sin reinicio requerido.

Baterías incluidas

Falcon incluye la infraestructura que un servicio en producción necesita, cada pieza detrás de una interfaz limpia:

ÁreaQué proporciona Falcon
API y middlewareEnrutamiento versionado basado en Gin (v1–v4), request-id / correlación, timeouts, recuperación de pánico, CORS, health / pprof y un endpoint de métricas
DatosGORM sobre Postgres, MySQL y CockroachDB; OpenSearch (con soporte de reindexación) para búsqueda y catálogo
CachéRedis con bloqueo distribuido, más AWS DAX
MensajeríaUna capa de streaming unificada — Kafka para publicar y consumir, con Kinesis y Google Pub/Sub en el lado de publicación
Flujos de trabajoUn motor de pipeline de solicitudes interno, más Temporal para trabajo durable y de larga duración
TransportesHTTP para llamadas entre servicios, con connection pooling y retry con backoff; con gRPC y los transportes de agentes de IA (SSE, MCP, agent-to-agent) en el roadmap
NubeUna interfaz sobre AWS y GCP para almacenamiento, secretos y KMS
SeguridadCifrado AES-GCM y firmas Ed25519 (con codecs Base32/64/Hex/Ascii85), autorización multi-estrategia, auth de servicio a servicio y enmascaramiento de PII
ObservabilidadLogging estructurado (zap, con envío opcional a Loki), métricas Prometheus y eventos de auditoría
ConcurrenciaGoroutine pooling con backpressure

Nada de esto es novedoso por sí solo — el valor es que es uniforme. Cada servicio accede a una base de datos, emite una métrica o firma un payload de la misma forma, de modo que un ingeniero que ha trabajado en un servicio Falcon es inmediatamente productivo en el siguiente.

También es opt-in: cada capacidad se activa por servicio en configuración (falcon.<feature>.enabled=true), de modo que un servicio lean lleva solo lo que realmente usa y no paga nada por el resto.

Cómo fluye una solicitud

De extremo a extremo, cada solicitud pasa por las mismas etapas ordenadas, de modo que el comportamiento es predecible sin importar qué servicio la maneje:

  1. 01Ingress. La cadena de middleware estampa un request y correlation ID y aplica timeout, métricas y CORS.
  2. 02Autenticar. El token del llamador se valida — un token OAuth Bearer verificado contra un servicio de auth central, o un JWT verificado localmente — y se extraen sus scopes.
  3. 03Autorizar. Una verificación multi-estrategia resuelve la identidad y permisos del llamador, con búsquedas de política por tenant cacheadas en Redis — Xeni está consolidando estas estrategias en IDAM.
  4. 04Ensamblar contexto. El context acotado a la solicitud se enriquece con config, clientes de base de datos y caché, clientes salientes, identidad de tenant y usuario, e IDs de correlación.
  5. 05Manejar. El handler de producto se ejecuta — típicamente componiendo el pipeline de flujo de trabajo de abajo.
  6. 06Responder. La salida se negocia por contenido — JSON por defecto, HTML y PDF para documentos orientados a humanos, y bytes crudos para archivos — con formateo automático de sobre de error. Las respuestas streaming (SSE, NDJSON) están en el roadmap; XML permanece disponible para consumidores legacy.
  7. 07Auditar. Los eventos de solicitud y flujo de trabajo, con campos sensibles enmascarados, se publican en el stream de notificaciones.

Cada solicitud corre la misma forma

Los servicios Falcon manejan solicitudes como un pipeline explícito en lugar de un enredo de código de handler:

ValidatorPolicyWorker(s)ErrorHandler

Un handler compone ese pipeline como una cadena fluida — el motor de flujos de trabajo de Falcon:

go
resp, err := workflow.NewWorkflowEngine("Booking").
    AddValidator(ctx, &InputValidator{}).
    AddPolicy(ctx, &FraudPolicy{}).
    AddWorker(ctx, &Booking{}, false).
    AddWorker(ctx, &Payment{}, false).
    AddErrorHandler(ctx, &ErrorHandler{}).
    Execute(ctx)

Su verdadero poder es que los workers son unidades de trabajo independientes. Cada uno implementa una interfaz pequeña — IsEligible, Skip y Execute — y el mismo worker puede componerse en diferentes flujos de trabajo para resolver diferentes necesidades de negocio. Un worker Payment escrito una vez se reutiliza en una reserva, un reembolso y una renovación de suscripción; un validator o fraud policy encaja en cualquier flujo que lo necesite.

El motor encadena las salidas de los workers, rastrea el estado por tarea en un WorkFlowStatus, emite un evento de flujo de trabajo en cada paso y enruta cualquier fallo al ErrorHandler registrado — dando a cada servicio estructura de handler consistente y lógica de negocio observable, testeable y componible.

Es el mismo patrón detrás del servicio de identidad de Xeni: una nueva capacidad es cuestión de escribir un worker y conectar una ruta.

Cambia el proveedor, no el código

Como las tecnologías de respaldo están detrás de interfaces, pueden cambiar sin tocar el código de producto. El proveedor de nube (AWS o GCP), la caché (Redis o DAX) y la columna vertebral de streaming (Kafka, Kinesis o Pub/Sub) se seleccionan por configuración y se resuelven a través de una factory. Un cambio de proveedor ocurre dentro del framework.

El efecto estratégico se compone: un nuevo servicio comienza con cero código de infraestructura, y el costo marginal del siguiente servicio — y del siguiente proveedor, mercado o producto — sigue cayendo a medida que el framework absorbe más del trabajo común.

Un patrón, servicios de propiedad cruzada

La plomería común es solo la mitad de lo que Falcon compra. La otra mitad es disciplina: porque el framework fija la forma de un servicio — un contrato de handler, un pipeline de solicitudes, una forma de alcanzar cada dependencia, un modelo de error y logging — cada servicio termina pareciéndose a todos los demás.

Esa uniformidad cambia cómo trabaja el equipo. Los ingenieros no están aislados en el servicio que les tocó construir; cualquiera que conoce un servicio Falcon puede leer, extender y depurar el siguiente. Los servicios son de propiedad cruzada en lugar de custodiados — lo que difunde conocimiento, elimina puntos únicos de fallo en el equipo y acorta la incorporación a días.

Importa más cuando algo se rompe. Los mismos logs, las mismas métricas y las mismas etapas de pipeline en cada servicio significan que quien esté de guardia puede orientarse dentro de un servicio desconocido y arreglarlo rápidamente — la resolución de problemas en vivo no espera a la única persona que lo escribió. Plomería compartida más patrones aplicados convierten "¿quién es el dueño de esto?" en "cualquiera de nosotros puede."

El resultado es apalancamiento: un equipo pequeño construye y opera una plataforma amplia, y la relación de servicios por ingeniero sigue mejorando a medida que el framework absorbe más del trabajo común.

Las compensaciones que asumimos

Una base compartida es una apuesta deliberada, y no es gratis:

  • Riesgo concentrado. Un bug en Falcon puede llegar a cada servicio a la vez. Eso eleva el listón: el framework lleva un estándar más alto de revisión, pruebas y versionado cuidadoso que cualquier servicio individual.
  • Exige profundidad. Falcon necesita experiencia real en Go y un equipo que trate el framework como un producto con su propio roadmap — no un proyecto secundario.
  • Tiene que estar adelante. El framework debe anticipar lo que los equipos de producto necesitarán después; cuando se queda atrás, cada equipo siente la fricción.

Asumimos esto porque la alternativa es peor. Dejar que cada equipo re-resuelva configuración, auth, acceso a datos y observabilidad produce entregas más lentas, comportamiento inconsistente y una postura de seguridad imposible de razonar de forma uniforme. Centralizar las partes difíciles es lo que permite al resto moverse rápido.

Por qué se mantiene

  1. 01Aislar infraestructura del producto. Un servicio debe contener lógica de dominio y poco más.
  2. 02Hacer que cada servicio se vea igual. Un contrato de handler, un pipeline de solicitudes, una forma de alcanzar cada dependencia.
  3. 03Poner la topología en configuración. Agregar una base de datos o un cliente downstream es un cambio de config, no una reescritura.
  4. 04Ocultar proveedores detrás de ports. Nube, caché y streaming pueden cambiar sin que el código de producto lo note.
  5. 05Tratar el framework como producto. Aceptar el riesgo concentrado y pagarlo con revisión, pruebas y versionado.

Valor estratégico de un vistazo

Retrocediendo de la mecánica, el beneficio de negocio es directo:

Objetivo de negocioCómo lo entrega Falcon
Entrega de producto más rápidaLos nuevos servicios comienzan con cero código de infraestructura — los equipos se enfocan en lógica de dominio.
Consistencia entre serviciosAuth, logging, métricas, eventos y manejo de errores se comportan de forma idéntica en todas partes.
Agilidad de proveedor y stack tecnológicoNube, streaming, caché y preocupaciones de capa web están abstraídas detrás de Falcon.
Escala horizontalServicios stateless, connection pooling, bloqueo distribuido y desacoplamiento por streams.
Seguridad y cumplimientoAuth centralizado, enmascaramiento de PII y criptografía respaldada por KMS aplicados de forma uniforme.
Madurez operacionalMétricas Prometheus, logs estructurados, endpoints de health y pprof, y eventos de auditoría listos para usar.

Cierre

Falcon es fácil de subestimar porque, cuando funciona, no lo ves: los servicios simplemente comienzan con la plomería ya resuelta. Pero es la razón silenciosa por la que Xeni puede operar una plataforma amplia — identity, payments, search y las verticales de producto — sobre un chasis común en lugar de un montón de soluciones únicas.

En pocas palabras, Falcon es el tejido conectivo de la plataforma: convierte lo que de otro modo serían docenas de decisiones de infraestructura independientes por servicio en un contrato único, versionado e impulsado por config. Por eso lo tratamos como un producto interno de primera clase — con maintainers dedicados, una cadencia de release estable y una política clara de deprecación para rutas legacy — no una utilidad compartida que nadie posee.

El framework es el apalancamiento: resolver infraestructura una vez e heredarla en todas partes. El ejemplo más claro de un servicio construido enteramente sobre ese apalancamiento es la capa de identidad de Xeni — el tema de la publicación complementaria, Dentro de IDAM.

Escrito para el blog de Ingeniería Xeni. Describe el framework Falcon a julio de 2026. El ejemplo de código es ilustrativo de la forma de la API del framework.