live on GKE right now

Real-time data
for hospital catering
built like SaaS.

A complete demo of MySQL → Debezium → Kafka → ClickHouse → Metabase + Grafana, modelling 220 hospitals, daily diet boxes, and a retail e-commerce shop. Every layer of the modern data stack — change data capture, native streaming, dimensional modelling, business intelligence, observability — wired together and running on GKE, provisioned by Terraform and deployed via ArgoCD GitOps.

0
hospitals
0
B2C subscribers
0
deliveries / 21d
0
live telemetry events
The problem

Catering operations run on spreadsheets and yesterday's reports.

Hospital meals are a low-margin, high-trust business: a single missed SLA can cost a contract, a single cold-chain breach can cost a license. The data exists — it's just stuck in five systems no leader can read together.

Stale dashboards

Yesterday's CSV refresh tells you about a problem after the contract is already on the table.

Disconnected systems

OLTP, fleet GPS, cold-chain sensors, billing — five sources, zero correlation.

No B2C insight

Diet box subscriptions and e-commerce live in different tools — leadership sees the trees, not the forest.

Operations vs. business divide

SREs need infra metrics; the COO needs revenue. One Grafana for both is a compromise nobody loves.

The fix

One pipeline. One source of truth. Two tools for two audiences.

MediCater OPS streams every business event from your operational MySQL into a ClickHouse warehouse via Debezium and Kafka — in seconds, not hours. Pre-aggregated KPIs power business dashboards in Metabase; raw infra metrics power on-call dashboards in Grafana. Both audiences win.

The architecture

Bronze ▸ Silver ▸ Gold.

A classic medallion architecture, fully implemented and visible end-to-end. Every metric on every dashboard can be traced back through three explicit layers of the warehouse.

MySQL 8.4
23 OLTP tables · binlog enabled · the operational source of truth
source
Debezium
+ Kafka
Bronze
medicater.* ReplacingMergeTree mirrors · raw CDC shape · exact dedup with FINAL
CDC mirror
etl container
60-s loop
Silver
medicater_dw.* star schema · 11 conformed dims · 5 fact tables · dim_date · 3 dictionaries
dim / fact
Gold
medicater.kpi_* AggregatingMergeTree rollups · 6 KPI tables · v_*_kpi convenience views
pre-aggregated
Metabase
8 business dashboards · ~80 cards · auto-provisioned via REST · for the COO
business BI
Grafana
5 ops dashboards · CDC pipeline · ClickHouse internals · Kafka lag · MySQL · SLO board · for the SRE
infra ops
Bronze
1:1 CDC mirror of OLTP. Source of truth, never edited. Use for audit + replay.
Silver
Curated star schema. Conformed dims, surrogate keys, derived attributes. Use for ad-hoc analysis.
Gold
Pre-aggregated narrow rollups. Sub-100 ms dashboard queries even at billions of rows.

Two ingest paths on purpose

Transactional state (orders, deliveries, contracts) flows through CDC for guaranteed ordering. Raw telemetry — GPS pings, cold-chain temperature, SLA micro-events — bypasses MySQL entirely and is consumed directly by ClickHouse's Kafka engine. Same warehouse, two well-suited shapes.

Three sales channels

One platform. Three revenue streams. Zero data silos.

CHANNEL · 01
Hospital catering
B2B core

Long-term contracts with hospitals. SLA-bound deliveries, breach penalties, contracted meal plans by tier.

Hospitals220
Active contracts220
Deliveries / day~1 500
SLA breach rate3 – 10%
CHANNEL · 02
Diet boxes
B2C recurring

Daily meal-kit deliveries to subscribers' homes. 10 plan SKUs from Slim 1200 to Sport 3000, monthly billing.

Subscribers1 500
Active subscriptions~1 050
Boxes / day~1 000
Plans10 SKUs
CHANNEL · 03
E-commerce
B2C transactional

One-off retail orders via web, mobile, marketplace, and partner apps. Cards, BLIK, transfers, COD.

Channels4
Payment methods5
Couriers6
Order ratelive
Capabilities

Everything a modern data platform should ship with.

Sub-second CDC

Debezium tails the binlog, Kafka transports, the Altinity sink lands rows into ClickHouse before the spinner ends.

Native streaming ingest

High-volume telemetry (GPS, cold chain, SLA events) bypasses CDC and hits the ClickHouse Kafka engine directly.

Dimensional warehouse

11 conformed dimensions, 5 fact tables, surrogate date_key, an incremental ETL container with checkpoints.

Pre-aggregated rollups

6 AggregatingMergeTree KPIs hand-tuned for dashboard latency. Sub-100 ms responses at billions of rows.

Fleet & fuel economy

Vehicle utilisation, daily km, L/100km, fuel cost in PLN by fuel type, driver safety scores. All live.

Cold-chain compliance

Per-vehicle temperature curves with realistic spikes on door-open events. Violations flagged automatically.

Revenue & penalty tracking

Monthly billing, top clients, per-region revenue, penalty leakage by hospital tier — all stitched through the contract layer.

SRE-grade observability

Prometheus scrapes ClickHouse, MySQL, Kafka, Connect. Five Grafana dashboards from CDC pipeline health to stack-wide SLO.

Live data simulator

Three threads continuously generate orders, telemetry, churn, and incidents with realistic seasonality and anomalies.

Auto-provisioned BI

A Python script pre-builds 8 Metabase dashboards via REST API. No clicking required — open and present.

Idempotent everything

Every script can be re-run safely. Bootstrap, backfill, ETL, dashboard provisioning — all check before they write.

GitOps deployment

12 workloads on GKE. Terraform provisions the cluster and edge, ArgoCD syncs every Deployment from Git. No manual kubectl apply.

The flow

From order placed to dashboard refresh — in seconds.

A single business event traces a clean line through the platform. Watch a hospital order travel from MySQL to the executive dashboard — under 5 seconds, every time.

01

Order placed

Hospital ops dispatches a meal order. The simulator (or your real OLTP service) runs INSERT INTO meal_orders. MySQL writes the row and emits a binlog event.

02

Debezium captures the change

The Debezium MySQL source connector tails the binlog, wraps the change in an envelope (op: c, before, after, source), and produces it to kafka_cdc.medicater.meal_orders.

03

Altinity sink writes Bronze

The ClickHouse sink consumes the topic, batches records, and inserts into the medicater.meal_orders ReplacingMergeTree mirror. _version is set from the source timestamp; deletes flip is_deleted.

04

Materialized views fire (Gold)

Each insert triggers mv_kpi_delivery_hourly, mv_kpi_hospital_daily, and the channel rollups. Aggregate state functions write to AggregatingMergeTree targets.

05

ETL ticks (Silver)

Once a minute, the etl container re-runs transform.sql: 11 dimension refreshes, 5 incremental fact loads keyed by etl_checkpoint. fact_delivery picks up the new row.

06

Dashboards refresh

Metabase's executive panel re-runs its query against v_delivery_hourly_kpi on its 30-second refresh interval. The new order is visible. The COO sees on-time % update in real time.

The stack

12 containers. Every one of them earned its place.

MySQL 8.4source · binlog
Debezium 2.7.3CDC source connector
Apache Kafka 7.7KRaft · 3 telemetry topics
Apicurio Registryschema management
Kafka ConnectDebezium + Altinity sink
ClickHouse 26.7analytics warehouse
Python simulator3-thread ops loop
ETL containerBronze → Silver every 60s
Prometheusinfra metrics
ExportersMySQL · Kafka · CH built-in
Grafana 13.15 ops dashboards
Metabase 0.638 business dashboards
Operate it

Built for the on-call engineer who lives in Grafana.

Operations is a first-class concern, not an afterthought. Five SRE-focused dashboards cover the whole stack — every layer of the pipeline has a metric you can alert on.

00 · CDC PIPELINE HEALTH

SLI: rows-per-INSERT, active parts, query latency

The on-call's home base. INSERT/SELECT rate, batching efficiency, ClickHouse merger backlog, p50 latency, SELECT-to-INSERT ratio. Alert when batching drops or parts pile up.

01 · CLICKHOUSE INTERNALS

Profile events, merges, mutations, memory, disk

Query rate, failed query rate, parts/tables/databases, background merge tasks, RSS, mark cache, uncompressed cache, file handles, data path utilisation.

02 · KAFKA HEALTH

Brokers up, throughput, partition leadership, consumer lag

Per-topic message rate, total cumulative offsets, lag by consumer group × topic. Alert when sink lag grows linearly.

03 · MYSQL SOURCE HEALTH

Connections, DML mix, InnoDB rows + buffer pool

Slow query rate, threads connected/running, command-type breakdown, InnoDB row activity (insert/update/delete/read), buffer pool used/free/dirty.

04 · STACK OVERVIEW & SLO

One-screen dashboard. Every component up/down. End-to-end ingest rate.

Big green/red component status row (CH, MySQL, Kafka, Connect, Prometheus). End-to-end ingest rate (MySQL inserts/s vs ClickHouse inserts/s). Total Kafka lag. ClickHouse RSS. Backpressure indicators. The board to flash on the wall.

Restart procedure

kubectl rollout restart deployment -n medicater <name> for a single component, or resync the app in ArgoCD to reapply everything from Git. Idempotent and safe.

Sink stuck?

Reset the topic offset: kafka-consumer-groups --reset-offsets --to-earliest --topic kafka_cdc.medicater.X --execute. Documented in CLAUDE.md.

End-to-end smoke test

./scripts/verify-cdc.sh compares MySQL row counts against ClickHouse FINAL counts and reports any drift.

Live now

Open the running stack.

Every link below resolves to a live Service running on GKE right now. Click and present.