Data Platform β Slice 1 (LIVE, ktayl IS #5)
:::tip This is deployed and proven (2026-09-27) Unlike the heavier design-reference stack in the rest of this section (Kafka/Redpanda β ClickHouse β Superset β OpenMetadata β still planned / need-first-deferred), Slice 1 is a light-first implementation that actually runs: dbt + CNPG Postgres + Metabase. It is the first thin vertical slice of the ktayl IS Data Platform (#5). :::
Two-layer model: this is the ktayl-solution IS analytics platform, not Retrieva.
Detailed docs (the library): ktayl-data-platform docs site β architecture, system design (C4 + NFRs + threat model), design patterns, and data model. Code (dbt + ingest + Metabase provisioner):
andrelair-platform/ktayl-data-platform. Deployment (k8s manifests, CronJobs, ArgoCD):minicloud-gitops/manifests/data-platform/β the CronJobs git-clone the code repo at runtime (deployment-vs-code separation). This page is the map.
The doctrine (why light-first, why one slice)β
Per the EA capability map roadmap: use cases drive it Β· sources constrain it Β· technology comes last. ktayl's sources are its own domain services, and most aren't built yet β so building a heavy OLAP cluster now would be "a warehouse for empty warehouses." The rule is one thin vertical slice against a real live source β just-enough medallion β one data product, then generalise from 2β3 real pipelines. Policy Admin is the one fully-live business source, so it's the slice.
Architectureβ
ktayl-policy-service (LIVE prod Postgres β the real source)
β ingest CronJob (full-refresh COPY; read-only analytics_ro role; CDC later)
βΌ
raw βββΊ curated (dbt staging) βββΊ business (dbt marts)
policies/coverages/premiums stg_* policy_portfolio βββ the data product
β dbt build = run + 26 schema tests (fail loudly on source drift)
βΌ
Metabase (metabase.10.0.0.200.nip.io β Tailscale + CA)
| Layer | Tool | Notes |
|---|---|---|
| Storage (medallion) | CNPG Postgres dp-postgres, schemas raw/curated/business | derived/rebuildable β 1 instance, no PITR |
| Ingestion | CronJob (pg COPY prodβraw) | full-refresh; CDC (DebeziumβNATS) is Slice 2 |
| Transform | dbt-postgres | stagingβmarts + tests; custom-schema macro so marts land in business |
| BI / serve | Metabase | own metadata DB on the same CNPG cluster |
ClickHouse/Kafka/Superset/OpenMetadata remain the future heavier target (need-first gate) β not required for a single-source slice.
The data product β business.policy_portfolio (grain = policy)β
- GWP proxy
annualised_premium_eurβ attacks P2 (margin/portfolio). - TIV
total_insured_amount_eurβ the exposure seed for P1/P3 (accumulation). - scheduled/paid premium,
coverage_count, dimsproduct_code/status/inception_year.
Status: pipeline proven end-to-end β a seeded [TEST] prod policy flows to the mart (GWP β¬12k / TIV
β¬1M, kept as a Metabase demo row). It fills with real data as prod policies are created.
Operateβ
# on-demand run (also runs daily 02:00 ingest / 02:30 dbt via CronJobs)
kubectl create job -n data-platform dp-ingest-manual --from=cronjob/dp-ingest-policy
kubectl create job -n data-platform dp-dbt-manual --from=cronjob/dp-dbt-build
kubectl exec -n data-platform dp-postgres-1 -- psql -U postgres -d analytics -c \
"SELECT * FROM business.policy_portfolio;"
Metabase is provisioned as code by the idempotent metabase/provision_dashboard.py in the
ktayl-data-platform repo; the access model
(Authentik forward-auth at the ingress) is covered on the
docs site.
Gotchas + hardening TODOsβ
- Cilium netpol: a standard NetworkPolicy
ipBlockdoesn't match the kube-apiserver identity β CNPG initdb hangs on10.43.0.1:443. data-platform uses Ingress-only netpols; harden later with a CiliumNetworkPolicytoEntities: [kube-apiserver, world]. - dbt schema naming: dbt concatenates target+custom by default (
business_business) β overridden via agenerate_schema_namemacro so marts land inbusiness. - TODO: Metabase Authentik SSO (local admin for now); confirm the money/premium (minor-unit + installment) assumptions with the Policy domain before the GWP figure is authoritative.
Next slicesβ
Slice 2 = add a second real source as the next domain ships (generalise ingestion from 2β3 real pipelines; CDC over batch), then MDM-keyed Customer 360 once MDM exists. See the capability map roadmap.