Architecture decisions.

Every component choice from the katas, with the reason and the alternative that lost.

Design studies, not delivered systems.

141 decisions in 10 katas.

Cold-Chain Telemetry and Compliance Platform

Reliable data19 decisions

NeedChoiceWhy
Device ingestEMQX with MQTT 5MQTT fits devices: tens of thousands of persistent connections, small messages, QoS 1 acknowledgements and sessions for offline clients. EMQX clusters and checks an X.509 certificate per device. Mosquitto and HiveMQ CE do not cluster.
Bridge from broker to logEMQX Kafka data integrationWrites to Kafka with acks=all and acknowledges the device only after Kafka confirms, so no MQTT offset can be lost. An Enterprise feature; the open alternative is Kafka Connect MQTT source, at least once.
Sources without MQTTIngestion API, HTTPS batch with an idempotency keyThe third vendor only offers portal exports. A second door into the same raw topic, where the idempotency key makes a resend harmless.
Event backboneApache Kafka with KRaft on StrimziAn MQTT broker is a distribution point, not a durable log. Kafka gives a replayable log ordered by device, and three replicas with acks=all prevent loss. Redpanda was ruled out over its Business Source License.
Schema contractApicurio Registry with AvroA versioned contract for three vendor formats and future ones. Incompatible changes fail in CI, not in production. Confluent Schema Registry was ruled out because of its Community License.
Transport reference dataDebezium change data captureReads the shipment, vehicle and driver mapping from the transport system's log, with no query load and no change to that system. Flink uses it as broadcast state.
Stream processingApache Flink with the Kubernetes operatorEvent time, watermarks, 72 hours of allowed lateness, stateful joins and rules in one place. Deduplication uses the monotonic sequence: the last number plus a small gap set per device, so 20,000 keys, not billions.
Hot analyticsClickHouse with the Altinity operatorSub-second time series queries over 90 days, with idempotent writes through ReplacingMergeTree on device and sequence. TimescaleDB was ruled out: its compression and continuous aggregates sit under the Timescale License.
Evidence archiveApache Iceberg on Ceph RGW with RookCheap object storage for ten years of raw data, an open table format with ACID snapshots, and write-once retention through S3 Object Lock. Ceph, because the MinIO community edition narrowed in 2025.
Operational statePostgreSQL with PostGIS on CloudNativePGShipments, geofences, alert state and last position: relational and geographic queries in one place. A boring and correct choice for small, hot, often-updated data.
Cache and pub/subValkeyRedis-compatible and BSD-licensed under the Linux Foundation, for the live position cache and WebSocket fan-out. Redis 8 returned to AGPL, which would also be acceptable; Valkey stays out of the licence debate.
Immutable ledgerimmudbReport digest, signature, Iceberg snapshot ID and report version go into an append-only ledger. Merkle proofs let an auditor verify independently that nothing changed. Codenotary offers enterprise support.
Secrets and keysOpenBaoDevice PKI, a tokenisation key per driver and transit signing. The Linux Foundation fork under MPL 2.0, since HashiCorp Vault moved to the Business Source License.
API gatewayApache APISIXOAuth2 validation, quotas per customer, versioning and WebSocket proxying. APISIX under the Apache licence, because Kong OSS moved enterprise features into its closed edition.
IdentityKeycloakOpenID Connect federated to the corporate identity provider for staff, and client credentials for business customers. Support comes through the Red Hat build of Keycloak.
Map and UIReact, MapLibre GL and Martin vector tilesAn own tile server means no fee per map call. MapLibre is the BSD-licensed fork made after Mapbox GL v2 went closed. Enough for 500 dispatchers.
Analytical accessTrino, Apache Superset, JupyterHubData scientists query Iceberg with SQL through Trino, dashboards run in Superset and notebooks in JupyterHub. The evidence archive doubles as the analytics source, so no copy is needed.
PlatformKubernetes or OpenShift, Argo CD, cert-manager, step-ca, CiliumEvery workload is operator-managed, and GitOps makes the setup reproducible. step-ca issues device certificates; Cilium enforces mTLS and network policy.
ObservabilityOpenTelemetry, Prometheus, Grafana, Loki, TempoDevice liveness, consumer lag, checkpoint health, alert delay from device time to delivery, and report backlog in one stack.

Open the kata: Cold-Chain Telemetry and Compliance Platform

Open Lakehouse with Data Contracts and a Shared Semantic Layer

Reliable data12 decisions

NeedChoiceWhy
Open table formatApache IcebergAll four engines read it, and the standard REST catalog protocol they implement is Iceberg's. Atomic snapshots, schema evolution, row-level deletes for erasure. Delta and Hudi lack an equal neutral catalog protocol: capability, not licence.
CatalogApache Polaris or Lakekeeper, both Iceberg RESTOne catalog with a warehouse per region and short-lived, table-scoped credentials for each engine. OPA policy applies here. Per-engine catalogs like Glue, Unity or BigLake metastore would mean three permission models.
Regional storageCloud Storage in the EU, S3-compatible in the UK, Ceph RGW on premises in TürkiyeData stays in its region, with one KMS key per region. Files are written once and never copied, so there is no seventh copy. Ceph over MinIO, given its licence and distribution doubts.
Cross-brand and group query engineTrinoIceberg connector, OPA row and column policies and a pool per region. It is also the on-premises brand's writer. Spark would work, but Trino suits interactive, federated queries better. Athena is commercial and single-cloud.
Data contractOpen Data Contract Standard YAML with CISchema, PII class, SLA, owner, version and chargeback label live with the table. CI blocks breaking changes before merge; a post-commit job tags snapshots. A catalogue entry filled in afterwards is not a contract.
Transformationdbt Core or DataformThe tools the brands already use, with model and contract in one repository and lineage for free. A new tool would be a migration in disguise. dbt Cloud and Semantic Layer stay out on purpose.
Semantic layerOpen metric spec in YAML, a custom compiler, a metric APIOne definition outside the engines, compiled into four SQL dialects and checked by a conformance suite. Power BI models or LookML tie it to one tool; dbt Semantic Layer depends on dbt Cloud.
Metadata catalogueOpenMetadataLineage from dbt and Iceberg snapshots, freshness against SLA, contract status and version notices. Apache 2.0. DataHub was a candidate, but OpenMetadata's quality and contract features are more mature.
PolicyOpen Policy AgentOne policy bundle in the catalog and in Trino: the single-writer rule, masking by region and role, and aggregate-only access for the group principal. Apache Ranger is heavier and centred on Hadoop.
IdentityKeycloakOpenID Connect for people and for engine service principals. One principal per brand and region, and a separate group principal.
OrchestrationApache AirflowGroup jobs only: regional aggregation, consolidation, reconciliation and the conformance suite. Brand pipelines stay in their own schedulers.
Observability, secrets and deliveryPrometheus, Grafana, Loki, Tempo, OpenTelemetry; OpenBao; Argo CDContract breaches, freshness, read latency per engine, chargeback and conformance drift on one dashboard. GitOps runs three regions from one repository. OpenBao, because HashiCorp Vault moved to BSL.

Open the kata: Open Lakehouse with Data Contracts and a Shared Semantic Layer

Regional Health Information Exchange

Reliable data14 decisions

NeedChoiceWhy
Source adaptersApache Camel with HL7, FHIR and FTP componentsOne stateless adapter per vendor, with HL7 v2 over MLLP, FHIR and file handling ready to use. Vendor quirks stay in the adapter. Mirth Connect moved to a closed licence in 2024.
Event backboneApache Kafka on StrimziA durable, replayable log ordered by source plus record number, so order holds per patient. The acknowledgement goes back only after commit. Redpanda was ruled out because of its Business Source License.
Schema and profile contractApicurio Registry and a FHIR Implementation GuideRaw envelope schemas and regional FHIR profiles are versioned, and incompatible changes fail in CI. Confluent Schema Registry was ruled out because of its Community License.
Canonical clinical storeHAPI FHIR JPA Server on PostgreSQLThe FHIR R4 reference implementation, with search, versioning and interceptors ready. Consumers never see a vendor format. IBM FHIR Server is no longer maintained; Smile CDR offers commercial support.
Patient matchingSplink with an own matching service and a PostgreSQL link tableProbabilistic matching is required for the 15% without a national ID. A merge is a row with its evidence and can be undone. Commercial master patient indexes such as IBM Initiate and Verato are closed.
Consent policyOpen Policy Agent with RegoConsent, identity, organisation and purpose of use in one policy bundle, run by the API, bulk export and research alike. Consent tables inside the data layer leak data in bulk reads.
Identity and authorisationKeycloak with SMART on FHIR and OpenID ConnectHospital identity federation, national e-ID brokering, SMART scopes and a purpose-of-use claim. Apache 2.0 with Red Hat support. Ory Hydra is the alternative.
API gatewayApache APISIX with an OPA pluginToken validation, the policy call, rate limits and audit headers. The FHIR server is reachable only through the gateway. APISIX, because Kong OSS moved features out of its open edition.
Audit ledgerimmudbA cryptographically verifiable, append-only record of who saw what and why, kept ten years and shown in the patient app. Amazon QLDB was ruled out: closed and tied to one cloud.
CacheValkeySub-millisecond reads for consent data and the precomputed patient summary. The cache key includes the consent version. Valkey over Redis because of the Redis 7.x licence change.
Raw archive and documentsCeph RGW with S3 Object LockRaw HL7 and FHIR messages and PDFs as immutable objects for ten years, and the source for replay. Ceph, because the MinIO community edition narrowed.
Research pipelineApache Flink, Apache Iceberg, TrinoDe-identification in the stream, one Iceberg table per project, and the university queries through Trino. Raw data never goes to the university.
Secrets and keysOpenBaoThe re-identification key is reachable only under the trusted third party's policy. Also PKI and database secrets. HashiCorp Vault was ruled out because of its Business Source License.
ObservabilityOpenTelemetry, Prometheus, Grafana, Loki, TempoFlow health per vendor, end-to-end freshness, matching rates, API p95 and audit write delay on one dashboard.

Open the kata: Regional Health Information Exchange

Enterprise Data Warehouse Migration to BigQuery

Reliable data13 decisions

NeedChoiceWhy
Data warehouseBigQuery, commercial and allowed by the requirementA board decision: serverless, columnar, EU multi-region. Reservations and byte caps make cost predictable; time travel and snapshots give a way back. Trino on Iceberg was not an option once the board chose BigQuery.
Change captureDebezium on Kafka Connect, Apache Kafka on StrimziStreams SQL Server change tables by log position, with a watermark per table that reconciliation reads. Datastream is managed but lacks older SQL Server versions and schema history. Redpanda was ruled out over its licence.
Initial bulk loadbcp and distcp to Avro in Cloud Storage, then BigQuery load jobs60 TB once per wave, about two days over Interconnect. BigQuery Data Transfer Service is an alternative, but Hadoop data needs distcp anyway. One method means fewer tools.
LandingGoogle Cloud Storage, EU, immutableAvro files by table and day. Every BigQuery layer can be rebuilt from landing plus Dataform. A lifecycle rule moves objects to Nearline after 90 days.
TransformationDataform with SQLXThe key to SQL Server specialists being productive in three months: they write SQL, not Java. Assertions per model, Git, and CI/CD only. dbt Core is the portable alternative; Dataform needs no extra infrastructure.
Core modelData Vault 2.0 with hubs, links and satellitesA source change touches only a satellite; marts and Power BI models stay put. Loads are idempotent MERGEs by business key and load time. A direct dimensional core would break marts on every source change.
OrchestrationCloud Composer, managed Apache AirflowNightly DAGs per domain, wave DAGs, watermark checks and the 05:00 target. Airflow is open source, and the DAGs stay portable.
Migration control planeQuarkus services on Cloud Run, Cloud SQL PostgreSQLDependency graph from SSIS XML, wave planner, reconciliation, a cutover switch per table and the close-owner flag. Commercial SSIS translators carry the packages' technical debt; dropping dead packages halves the work.
ReconciliationReconciliation service with Great ExpectationsRow counts, column sums and a canonical row hash per partition, on both sides. Each difference is classified and its rule goes into the transformation. Great Expectations adds thresholds and a readable report.
Compatibility interfaceLegacy view schema in BigQuery, reverse sync to the existing SQL ServerForty consumers cannot change on one day. Old names live on as views, and 15 T-SQL consumers get a nightly reverse sync. No new SQL Server licence. Babelfish exists only on AWS, with partial T-SQL.
Catalogue, lineage, policy tagsDataplex and BigQuery policy tagsPersonal data columns are tagged in staging, access goes through policy tags, and an audit dataset logs reads. OpenMetadata is the open alternative; Dataplex gives BigQuery lineage automatically.
IdentityKeycloak with OpenID Connect, Google Cloud IAM groupsKeycloak for the migration cockpit and Grafana. BigQuery access goes through IAM groups per domain, never per-user grants.
ObservabilityPrometheus, Grafana, Cloud Monitoring, a Logging sinkReconciliation differences, batch finish time, bytes per domain and legacy view use on one dashboard. Audit logs flow into BigQuery for GDPR Article 30 records.

Open the kata: Enterprise Data Warehouse Migration to BigQuery

Real-Time Fraud Decisioning for Instant Payments

Decisions12 decisions

NeedChoiceWhy
Mainframe bridgeKafka Connect IBM MQ source and sinkThe mainframe only speaks MQ. The connector reads at least once, and a replayed message is dropped by payment ID against the compacted decisions topic. IBM publishes the connector under Apache 2.0.
Event backboneApache Kafka on StrimziA durable, replayable log ordered by customer key, where decision and snapshot share one transaction. One cluster stretched across both data centres, not two clusters joined by MirrorMaker 2.
Schema contractApicurio Registry with AvroVersions the canonical PaymentRequest and snapshot schemas, and incompatible changes fail in CI. Confluent Schema Registry was ruled out because of its Community License.
Streaming featuresApache FlinkKeeps 90-day windows such as velocity, beneficiary history and device novelty as state. Computing them at query time would eat the 150 ms. Precomputing turns the lookup into one GET.
Online feature storeValkeySub-millisecond GET with a local replica in each data centre. A BSD-licensed Redis fork, chosen because Redis 7.x moved to source-available licences. A fast path only, not the source of idempotency.
Decision serviceQuarkus with Drools and ONNX RuntimeRules and model run in one process, so there is no network hop. Drools rules hot-reload and are versioned. ONNX Runtime runs a model from any training framework on CPU in milliseconds.
Snapshot archive and offline storeApache Iceberg on Ceph RGW with Object LockCheap, immutable storage for seven years of snapshots, in a table format that Spark and Trino both read. Ceph, because the MinIO community edition narrowed.
Training and model registryApache Spark and MLflowTraining joins snapshots with analyst labels, so it uses the features the model actually saw. MLflow holds versions, metrics and approvals, and moves the champion pointer.
Case managementPostgreSQL with custom servicesAlert queue, analyst outcomes and rule metadata. Small, relational and auditable.
Gateway and identityApache APISIX and KeycloakAnalyst and auditor screens use OpenID Connect, federated to the bank's identity provider, with roles and an audit log. APISIX, because Kong OSS moved features out of its open edition.
Secrets and keysOpenBaoConnector credentials, encryption keys and PKI. The MPL-licensed fork of Vault, since HashiCorp Vault moved to the Business Source License.
ObservabilityOpenTelemetry, Prometheus, Grafana, Loki, TempoPer-stage traces show where the 150 ms goes. The Grafana stack's AGPL licence is OSI-approved and creates no obligation for internal use.

Open the kata: Real-Time Fraud Decisioning for Instant Payments

BSS Modernisation and Real-Time Customer 360

Decisions15 decisions

NeedChoiceWhy
Mainframe change captureDebezium Db2 connector on Kafka ConnectReading the Db2 log through ASN capture tables is measurable and leaves the application schema alone. Querying tables directly would burn mainframe CPU. ASN Capture itself is a licensed IBM component.
Write path to the mainframeAnti-corruption layer (ACL) service with Kafka Connect IBM MQ sinkThe ACL turns a TM Forum order into an MQ transaction the mainframe already knows, with a correlation ID and a dedupe record before sending. The old model never leaks into the new domains.
Identity resolutionCustomer crosswalk owned by the CRM domain, with master data matching rulesThe same person lives under different IDs in 14 systems. Matching on national ID and contract number gives a confidence score. Below the threshold it shows as a possible match and is never merged.
Satellite systemsDebezium for PostgreSQL, Oracle and MySQL, plus file and API adaptersTwelve sources expose their logs, so change data capture gives the lowest load and best freshness. The two nightly-file sources carry their own freshness flag. No source pretends to be real time.
Event backboneApache Kafka on StrimziA durable, replayable log ordered by customer key. Compacted canonical topics can rebuild the read model without going back to the source. Redpanda was ruled out because of its Business Source License.
Schema governanceApicurio Registry with Avro and TM Forum schemasCanonical and business event schemas are versioned, and backward compatibility is enforced in CI. Confluent Schema Registry was ruled out because of its Community License.
Read model builderApache FlinkA stateful join of 14 streams on 20 million golden customer keys is exactly Flink's job. Exactly once into Kafka; at least once with idempotent upserts into PostgreSQL and OpenSearch.
Read model storesPostgreSQL on CloudNativePG and OpenSearchCommand and query separation: the app reads one document from PostgreSQL, agents search in OpenSearch. OpenSearch over Elasticsearch because of the SSPL and AGPL dual-licence period.
Order workflowsTemporalA 10-second order includes a mainframe MQ step and compensation. Temporal keeps state durable, retries and makes timeouts visible. Camunda 8 was ruled out after its move to a source-available licence.
Cohort routingUnleashCutover and rollback must be a flag flip. The gateway and the workflow read the same flag. LaunchDarkly is commercial. Unleash keeps SSO and RBAC in its paid edition, but cohorts are open.
Data meshApache Iceberg on Ceph, Trino, DataHubDomain teams own their data products, with catalogue, lineage and SLA in DataHub. The centre provides platform and standards, not the data. Ceph, because the MinIO community edition narrowed.
Churn modelApache Spark, MLflow, SHAP, ONNX servingDaily scores for 20 million subscribers are a batch job, and event-triggered rescoring uses the exported ONNX model. SHAP reason codes explain scores to agents. Pseudonymised features are still personal data under GDPR.
Gateway, identity and policyApache APISIX, Keycloak, Open Policy AgentTM Forum Open APIs behind one gateway, with OpenID Connect for subscribers and agents. OPA enforces purpose-based access to usage data in the gateway and in Trino. APISIX, because Kong OSS cut features.
Secrets and keysOpenBaoMainframe credentials live only in the ingest namespace, and the pseudonymisation key stays in-house. HashiCorp Vault was ruled out because of its Business Source License.
ObservabilityOpenTelemetry, Prometheus, Grafana, Loki, TempoMainframe CPU budget, capture lag, order step traces and the dual-run difference rate on one dashboard. It is the migration committee's single input.

Open the kata: BSS Modernisation and Real-Time Customer 360

Unified Marketing Intelligence on Google Cloud

Decisions14 decisions

NeedChoiceWhy
GA4 streaming ingestServer-side Google Tag Manager collector, Pub/Sub, BigQuery subscriptionGA4 has no native Pub/Sub export. A BigQuery subscription needs no code, and a streaming view meets the two-minute target. Dataflow only for real enrichment; one Dataflow job per stream is needless cost.
Batch file ingestCloud Composer, managed AirflowCompetitor files need retries, backfill and dependencies, a classic orchestration problem. Airflow is an open standard, and the managed service keeps the DAGs portable.
API ingestCloud Run connector serviceSocial, Ads and Search Console APIs need token handling, rate limits and a watermark per source. A small, stateless service that scales; Composer only triggers it on schedule.
Warehouse accessAuthorised viewsThe warehouse already sits in BigQuery in the same organisation; no Analytics Hub listing needed. A copy adds cost and a second truth. Views read the same rows, and the data team keeps ownership.
Storage and computeBigQuery with layered datasetsEvery source already lands here; another engine means a second copy and a second truth. Marts are partitioned by event date. This lock-in is deliberate; Trino or ClickHouse on Iceberg is the named alternative.
TransformationDataform with SQL and assertions in GitSQL with versions and a dependency graph, and the assertions are the publish gate's test set. The same model can be rebuilt in dbt Core, so the dependency is low.
Publish gateDataform assertions and a view swap by publish IDCandidate tables are built and tested, then CREATE OR REPLACE VIEW points the marts at them. On failure the views stay on yesterday. Rollback is a view change, with no reload.
Semantic layerMetric contract in Git and a metric API on Cloud RunThe heart of the design, and deliberately our own code. One definition feeds Power BI, the LLM and the agents. Cube or dbt Semantic Layer could replace it, but the definition stays ours.
BIPower BI tabular model, import with incremental refresh400 users are trained, it is the company standard and the licence exists. Import mode keeps clicks away from BigQuery. Measures and row-level roles are generated from the contract. Superset is the open alternative.
LLMVertex AI Gemini on EU endpointsThe model turns a question into metric, filter and date range as structured output; the metric API produces the number. Data stays inside the perimeter. An open-weight model on vLLM would keep the same interface.
AgentsVertex Agent Engine with an approval queueThe tools are the metric API, the catalogue and a proposal writer. There is no raw SQL tool and no direct Ads change. Every action is stored with evidence, approver and a rollback record.
ML feedVertex AI Feature StoreFeatures come from the same marts, so there is no second pipeline and the model uses the report's definitions. Feast on BigQuery follows the same pattern.
Catalogue and contractDataplexCertified versus raw shows as a badge. Lineage is native in BigQuery, and Dataplex tags carry contract version and freshness target. Metadata can be exported to OpenMetadata.
Identity, privacy and secretsIAM, policy tags, row access policies, Cloud DLP, Secret ManagerColumn policy tags stop the marketing role from selecting identifiers. Row access policies filter brand and country on ad-hoc and LLM paths. API tokens rotate automatically.

Open the kata: Unified Marketing Intelligence on Google Cloud

Competitor Price and Markdown Intelligence Platform

Decisions14 decisions

NeedChoiceWhy
Collection law and courtesySite registry in Git and a BigQuery tableRobots rules, rate, country legal status and selector version in one place; no worker starts without its row. Legal can stop a country without an engineer. A config file inside the worker cannot be audited.
Collector fleetCloud Run Jobs with Playwright and HTTP workersScales to zero when done, with one job and token bucket per site and country. An idle Kubernetes pool still bills; Cloud Functions are too limited for a browser. Plain HTTP stays the cheap path.
Fixed egress addressesCloud NAT with a registered IP per countryLegal needs to know which address we collect from. Proxy rotation counts as evading blocks and is out of scope. Each country gets a declared IP and an honest user agent.
SchedulingCloud Composer, managed AirflowDaily plans, retries, re-parse campaigns and supplier files are classic orchestration. The DAGs stay portable.
Raw snapshot storeCloud Storage bronze with a five-year retention lockReproducibility only comes from an untouched source, and the lock stops deletion even by admins. Raw HTML in BigQuery would be expensive and cannot be locked. The Archive class keeps five years affordable.
EventsPub/SubCaptured, parsed and matched events trigger the next stage instead of direct calls. Kafka would be too much here: no stream processing, no ordering need, a few tens of millions of small messages a day.
ParsingCloud Run service with versioned selectorsA stage separate from collection. When a selector breaks, snapshots are parsed again and the site is not visited again. Personal data such as review authors is dropped here and never reaches the bronze tables.
MatchingRules, Vertex embeddings with pgvector, Gemini in the grey zone, a human queueRules and embeddings settle about 80% deterministically. The LLM sees only the grey zone, with a daily cap and 5% sampled review. pgvector is open and portable; Pinecone-style managed services add needless dependency.
Warehouse and transformationBigQuery EU and Dataform with bronze, silver and goldA partitioned, columnar warehouse for five years at 8 million rows a day. Running our own cluster would break the fixed budget. Dataform SQL lives in Git and stays compatible with dbt.
Index, elasticity and adviceBigQuery ML and a SQL rule engineThe daily run is deterministic: same input, same output. Rules draw the decision space and the model only ranks within it. A separate Vertex model service is unnecessary for a daily batch.
Serving and identityIntelligence API on Cloud Run, KeycloakA read-only API. No service account can write to the pricing system, so "advice only" is enforced by IAM. Keycloak gives open-source OpenID Connect and country roles.
Trend summaryGemini, weekly, with citations requiredEvery sentence cites a raw snapshot and carries a "summary" label; uncited sentences are not produced. Golden, drift and injection tests run on every release.
LLM tracing and evaluationLangfuse on Cloud Run and Cloud SQLEvery LLM call is traced with cost and output, and evaluation runs gate releases. The core is MIT-licensed. Managed tracing products would move data outside the perimeter.
DashboardLooker Studio with BI EngineA free dashboard on gold, with the legal team's collection audit view in the same place. Superset is the open alternative but needs one more service to run.

Open the kata: Competitor Price and Markdown Intelligence Platform

Governed GenAI Data Agents with LLM Evaluation

AI & GenAI14 decisions

NeedChoiceWhy
API gateway and identityApache APISIX and KeycloakOpenID Connect login, then a short-lived signed user claim that travels with every agent and tool call. Per-user rate limits and an audit log. APISIX, because Kong OSS moved features out of its open edition.
Agent runtimeLangGraph on KubernetesAgent steps form an explicit graph. Tool calls are schema-checked, each agent's tool allow-list comes from Git, and every step emits a span. Managed frameworks like Bedrock Agents hide the tool surface and traces.
Model gatewayLiteLLMTwo providers and vLLM behind one OpenAI-compatible interface. Provider keys live only here, with quotas per team, routing per agent and cost labels. Restricted documents route only to vLLM. The MIT core is enough.
Open-weight model servingvLLM with a 32B model under Apache 2.0Two replicas with tensor parallelism of two cover the estimated peak of about 1,760 tokens a second. The on-premises path for sensitive document classes and for cost. The Llama community licence is not OSI-approved.
Metric APICertified definitions built with Dataform, plus a thin serviceThe agent picks a metric ID and filters; the layer compiles SQL and applies the user's row and column policy. Free text-to-SQL caused the wrong revenue figure, so it is closed by design.
Catalogue and data productsOpenMetadataAgents see only products with a contract for schema, owner, SLA and policy; lineage and owner go into the evidence. DataHub is also Apache 2.0, but OpenMetadata's contract and policy model is more direct.
Document store for retrievalPostgreSQL with pgvector, and OpenSearchAccess list and class label per document come from the document system. The permission filter runs before vector ranking, so the model never sees an unauthorised chunk. OpenSearch over Elasticsearch after its licence change.
Policy decisionOpen Policy Agent as a sidecarDecides agent, user and resource in every tool service. Allow-lists and class policies are versioned bundles in Git, and every denial is counted. Policy is enforced on the data, not in the prompt.
Evidence store and archiveOwn PostgreSQL evidence store, outbox, Debezium, Apache Iceberg for two yearsEvidence row and outbox row in one transaction; the answer is released only after commit. Langfuse v3 cannot take an outbox row because of its ClickHouse store and async ingest, so evidence lives separately.
LLM observabilityLangfuse v3 with ClickHouse, Valkey and blob storageSpans, latency, tokens and evaluation scores, ingested asynchronously for observability only. Valkey because of the Redis 7.4 licence. Arize Phoenix was ruled out over its Elastic 2.0 licence.
Evaluation platformOwn CI runners, Langfuse evals, a policy file in GitGolden set, tool-order score, injection and exfiltration suites, and a provider tolerance test per agent. Thresholds sit in a versioned policy file. Commercial eval services such as LangSmith were ruled out.
Approval flowFlowable with BPMNEvery action with a side effect becomes a human task, recording who approved what and when, with rollback. Approval never runs automatically. Camunda 8 was ruled out after its move to a source-available licence.
Deterministic productionCloud Composer and DataformThe onboarding agent drafts code and contracts at design time; a person reviews and merges. Composer runs the merged code without an LLM. Chosen because it is already a platform component.
Governance register and costPostgreSQL with a small UI, LiteLLM labels, GrafanaAgent, risk class, owner, evaluation status, allowed models, incidents and EU AI Act duties. The register is a release precondition. Daily cost per agent and team comes from LiteLLM labels.

Open the kata: Governed GenAI Data Agents with LLM Evaluation

Claims Intake with Document Intelligence

AI & GenAI14 decisions

NeedChoiceWhy
Multichannel intakeApache CamelIMAP, REST and SFTP connectors are ready, and every channel produces the same claim.received event and storage layout. A route per channel instead of custom code. Apache 2.0 with Red Hat support.
Document storeCeph RGW with S3 Object LockOriginals and OCR text stay unchanged for seven years. GPU workers and Iceberg use the same store through the S3 API. Ceph, because the MinIO community edition narrowed.
Event backbone and GPU job queueApache Kafka on StrimziClaim events and GPU jobs share one backbone; the priority and batch lanes are two topics. The queue absorbs GPU outages. I reused Kafka instead of adding RabbitMQ. Redpanda was ruled out over its licence.
Text recognition and document classesPaddleOCR or docTRFast on GPU, with layout and table extraction, under Apache 2.0. Commercial OCR APIs are excluded because no data may leave the company. Tesseract is too weak on photographed documents.
Language model servingvLLM with an open-weight modelContinuous batching gets the most from 8 GPUs. Output is constrained to a JSON schema, with confidence from calibrated log-probs. Apache 2.0 weights such as Qwen or Mistral; Llama's licence is not OSI-approved.
Vision modelOpen-weight vision model on vLLMDamage class and duplicate-photo detection in the same serving layer, with its own model record. A separate vision platform is unnecessary.
WorkflowFlowable with BPMNEvery step from intake to payment is visible, with SLA timers and escalation built in. Human approval is a task type. Camunda 8 went source-available, and Camunda 7 is in maintenance mode.
Rule engineDrools with DRL and DMNSimple claims under 2,000 EUR are decided by deterministic, versioned, testable rules. The reason for a negative decision comes from the fired rule. This is where "the model does not decide" becomes concrete.
Fraud graphPostgreSQL with Apache AGERepeat and ring patterns across repair shops, parties, invoices and accounts in Cypher, in the same database as the relational data. Neo4j Community is GPL and its clustering is commercial. JanusGraph adds operational load.
Decision audit recordPostgreSQL outbox, Debezium, Apache Iceberg on CephThe audit row and outbox row go into Flowable's PostgreSQL transaction, and Debezium publishes from the log, so there is no dual write. Iceberg keeps seven years, and auditors query it with Trino.
LLM tracingLangfusePrompt, version, tokens and latency for every call, plus evaluation scores and shadow comparisons. The core is MIT-licensed; the commercial enterprise features are not needed.
Model and prompt registryMLflow and GitWeight hash and version in MLflow; prompt templates and the evaluation set in Git, with a nightly regression run on a GPU. Promotion needs four-eyes approval, and rollback is a pointer change.
Gateway and identityApache APISIX and KeycloakAdjuster, investigator, auditor and customer roles through OpenID Connect, with a gateway audit log and rate limits. APISIX, because Kong OSS moved features out of its open edition.
Secrets and keysOpenBaoEnvelope encryption with a data key per claim. Destroying the key at the end of retention is erasure; a litigation hold keeps it. HashiCorp Vault was ruled out because of its Business Source License.

Open the kata: Claims Intake with Document Intelligence

Facing a design problem like these?