Federated¶
This example runs sutura for one user over two data systems. The metric recurring_revenue is in
Postgres, and its dimension segment is in ClickHouse. DataHub is the catalog. One question reads
both.
The example is in
examples/federated:
| Path | Contents |
|---|---|
conf/base.yaml |
The sutura settings |
compose.yaml |
Postgres with TLS, ClickHouse, a live DataHub, and the catalog loader |
postgres/init.sql |
The fact table fct_subscription_monthly |
clickhouse/init.sql |
The dimension table dim_customer |
loader/load.py |
The catalog that the loader writes into DataHub |
setup.sh |
Writes the secrets of the local services to .env and .local |
The rows are the CSV files of the single player example. All data is synthetic.
The settings¶
# sutura's settings for this example. One metric from Postgres, grouped by one dimension from
# ClickHouse. Both sources run as the deployment's own user, and DataHub says which platform is
# which source.
server:
host: "127.0.0.1"
port: 8080
security:
identity: "single-user"
single_user_because: "one operator reads both sources as the deployment's own user"
catalogs:
# DataHub, read with one token for every caller.
- name: "datahub"
kind: "datahub"
# Required for every catalog kind, and not read for DataHub.
dir: "/unused-for-datahub"
data_dir: "/unused-for-datahub"
version: "example"
endpoint: "http://127.0.0.1:8081"
token_file: "/run/sutura/datahub-token"
metric_property: "sutura"
# A dataset on the `postgres` platform is read from the source `billing`, and one on the
# `clickhouse` platform from the source `crm`.
platforms:
postgres: "billing"
clickhouse: "crm"
sources:
billing:
kind: "postgres"
host: "127.0.0.1"
port: 5432
database: "federated"
user: "sutura"
password_file: "/run/sutura/postgres-password"
transport_mode: "verified"
transport_anchors: "/run/sutura/postgres-ca.pem"
posture: "shared-service-user"
crm:
kind: "clickhouse"
host: "127.0.0.1"
port: 8123
user: "default"
password_file: "/run/sutura/clickhouse-password"
transport_mode: "plaintext"
posture: "shared-service-user"
platforms maps the platform of each DataHub dataset to the source that serves it. The dataset
fct_subscription_monthly is on the platform postgres, so sutura reads it from billing. The
dataset dim_customer is on clickhouse, so sutura reads it from crm. Both sources run as the
deployment's own user, and single_user_because records why.
The question¶
{
"metrics": ["recurring_revenue"],
"grain": "month",
"range": { "start": "2026-06-01", "end": "2026-07-01" },
"dimensions": ["segment"]
}
The metric is on the model postgres__fct_subscription_monthly. The dimension segment is on
the model clickhouse__dim_customer, reached through the relationship subscription_customer.
sutura reads the fact rows from Postgres and the dimension rows from ClickHouse, and joins them.
Run it¶
From examples/federated:
./setup.sh
docker compose up -d --wait postgres clickhouse datahub
docker compose run --rm federated-loader
The files in .local are the files that conf/base.yaml reads from /run/sutura:
datahub-token, postgres-password, postgres-ca.pem and clickhouse-password. Every port of
these services binds to 127.0.0.1 only.
Start sutura in a second terminal. It stays in the foreground. SUTURA_CONFIG_DIR names the
directory that holds base.yaml, and the container reads the files in .local as its own user. It
uses the host network, as in the single player example. The image tag ends in
-musl: that image carries the Postgres driver, and the plain tag does not:
export SUTURA_VERSION=0.10.0
docker run --rm --network host --user "$(id -u):$(id -g)" \
-v "$PWD/conf:/conf:ro" -v "$PWD/.local:/run/sutura:ro" -e SUTURA_CONFIG_DIR=/conf \
ghcr.io/telekom/sutura:$SUTURA_VERSION-musl serve
Post the question:
curl -s -X POST http://127.0.0.1:8080/v1/query \
-H 'content-type: application/json' \
-d '{"metrics":["recurring_revenue"],"grain":"month","range":{"start":"2026-06-01","end":"2026-07-01"},"dimensions":["segment"]}'
Related¶
- DataHub: the catalog settings, including
platforms. - PostgreSQL and ClickHouse: the source settings.
- Metrics layer: the same DataHub loader, with Cube.