Analytics fabric
Reports, Dashboards, Models, Metrics, Perspectives — compiled from the product model, routed across analytics substrates.
Vadyl's analytics plane is a first-class Vadyl module — not a bolted-on BI tool. Reports, Dashboards, Semantic Models, Metrics, and Perspectives are typed canonical entities. The Universal Model Graph (UMG) compiler resolves them against your product's entities and pushes execution down to whichever analytics substrate you bound.
What ships
- Reports — typed structured query specifications (dimensions, measures, filters, breakdowns).
- Dashboards — compositions of reports + filters shared across an organization.
- Semantic Models — typed model-of-models layer with dimensions, measures, joins, hierarchies. Compiles down across substrates.
- Metrics — first-class business metrics with definitions, filters, time grains, and unit semantics.
- Perspectives — projections over the model tailored to a specific audience or analysis question.
- Materialization plans — declarative pre-compute plans for metrics that need fast-path serving.
Compile pipeline IS the explain pipeline
Vadyl's analytics compiler is the explain pipeline (anti-pattern #78). Asking "why did this report return what it did?" runs the same internal pipeline as executing the report — never a log-derived approximation. Reason codes are stable across releases.
Substrate routing
Analytics substrates plug in through the same capability-surface contract as everything else (CapabilitySurfaceKind.AnalyticsSubstrate = 5). Built-in baseline ships BuiltInBaselineAnalyticsSubstrateConnector; BigQuery, Snowflake, ClickHouse, DuckDB connectors plug in as peers.
Define a metric
// src/analytics/metrics/Revenue.ts
import { metric } from "@vadyl/sdk";
export default metric.define("Revenue", {
source: "Order",
measure: metric.sum("total"),
filter: metric.where("status", "in", ["paid", "fulfilled"]),
timeGrain: ["hour", "day", "week", "month"],
unit: { kind: "currency", currency: "USD" },
});Define a report
// src/analytics/reports/RevenueByCustomer.ts
import { report } from "@vadyl/sdk";
export default report.define("RevenueByCustomer", {
metrics: ["Revenue"],
dimensions: ["Order.customer.name"],
filter: report.where("Order.createdAt", ">=", "now-30d"),
sortBy: { metric: "Revenue", order: "desc" },
limit: 50,
});Privacy gates
Every analytics query is access-evaluated against the sameAccessModel as entity reads. Dimensions and measures the actor cannot read are dropped from the result; if the result would be empty after enforcement, the query returns the typed privacy-filtered diagnostic instead of a fake empty.
Lineage
Every metric, report, dashboard carries typed lineage edges into the canonical Plane Capability Graph. Renaming a field, retiring a relation, or migrating an entity surfaces every dependent analytics artifact in the impact analysis.
Materialization
Slow metrics or hot dashboards declare materialization plans: pre-compute schedules, refresh policies, dependency graphs. Vadyl runs them through the scheduling plane and serves the precomputed results from the analytics substrate when the query plan matches.