The semantic layer

One governed model.
Every consumer, the same right number.

DataHashi sits between your warehouse and everything that queries it — LLMs, BI tools, embedded apps, internal services — so nobody recomputes the same metric a different way.

p99 ≤ 14ms
semantic-query.json → compiled.sql
You send

  "metrics": ["average_order_value"],
  "dimensions": ["customer.region"],
  "grain": "month"
We run
SELECT date_trunc('month', o.order_date),
  c.region, SUM(o.amount)/COUNT(o.id)
FROM rollup_orders o
JOIN dim_customer c ON ...
-- served from a rollup, not the warehouse
Fan-out-safe SQL Sub-second rollups Tenant-isolated
Works with your stack
Snowflake BigQuery Postgres MySQL DuckDB / lake
The problem

Built for teams done writing the same join twice.

SQL sprawls across dashboards, notebooks, and app code. Definitions drift, LLMs invent joins and return confidently-wrong figures, and the warehouse bill keeps climbing. DataHashi puts one governed model in the middle — and pushes the hard parts down to where they belong.

Less, but better

Name the metrics you want. You never write a join or an aggregation by hand.

Correct by design

Fan-out-safe SQL and governed metrics — the same number everywhere.

Sub-second

Answered from pre-aggregated rollups. p99 ≤ 14ms, never touching the warehouse.

Pushed down

Processing happens in the database. The layer stays thin; the source does the work.

Self-serve, no config files

From warehouse to governed API, in four steps.

Sign up, connect a warehouse, publish a model, query. No restarts, no YAML deploys — a runtime control plane.

01

Connect

Sign in with an email magic code and register your warehouse. Credentials are sealed with AES-256-GCM behind an SSRF-safe egress policy.

02

Introspect

We profile the source — cardinality, nullability, FK candidates — and propose a draft Semantic Model in native YAML for you to bless in the UI.

03

Publish

Promote governed Metrics on top of your Measures, set per-tenant RLS and cost policy, and we pre-build the rollups your registered queries need.

04

Query

Mint a data-plane API key and query via REST or MCP. Hits are served sub-second from tenant-partitioned rollups; misses fall back to a live run.

The platform

A semantic layer for the AI-native stack.

One thesis, carried by every module: compile a structured query to SQL, push execution down, and serve the hot path from pre-aggregated data.

A governed business model

Entities, Dimensions, Measures, and Metrics map your physical tables to business vocabulary — independent of any storage dialect.

Semantic Model

You never write the join

Name the metrics and dimensions you want. The compiler traverses the Join Graph and generates fan-out-safe SQL — correct even across one-to-many.

Join Graph

Sub-second hot path

Embedded and BI queries are served from pre-aggregated rollups by DuckDB over Parquet. Benchmarked p99 ≤ 14ms.

Rollups · p99 ≤ 14ms

LLM-native by design

Agents call MCP tools that emit a structured Semantic Query — never raw SQL. No hallucinated joins, no wrong numbers.

MCP

Multi-tenant, bring your own

Every tenant brings its own warehouse connection. Secrets are AES-256-GCM sealed; rollups are physically tenant-partitioned; RLS rides every read.

Isolation by design

Any warehouse, one port

Snowflake, BigQuery, Postgres, MySQL, DuckDB — each a renderer behind a single closed Dialect port. We generate SQL, never parse it.

Multi-dialect
The interface

Ask for the number. We write the SQL.

A Semantic Query is a structured object — metrics × dimensions × filters × grain. Every consumer emits the same shape; the compiler turns it into correct, dialect-specific SQL.

semantic-query.json what you send

  "metrics": ["average_order_value"],
  "dimensions": ["customer.region"],
  "grain": "month",
  "filters": [
    "field": "order.status",
    "op": "=", "value": "paid"
  ],
  "order": ["month"],
  "limit": 100


// no joins. no aggregation.
// no dialect. no rollup names.
compiled.sql what we run
-- fan-out-safe · Join Graph resolved
-- served from a covering rollup
SELECT
  date_trunc('month', o.order_date) AS month,
  c.region,
  SUM(o.amount) / NULLIF(COUNT(o.id),0)
    AS average_order_value
FROM rollup_orders o
JOIN dim_customer c
  ON o.customer_key = c.customer_key
WHERE o.status = 'paid'
GROUP BY 1, 2
ORDER BY 1
LIMIT 100;

average_order_value is a Metric — a ratio of two Measures computed after aggregation, not avg(amount). region lives on Customer; the compiler walks Order → Customer to reach it. You just listed them.

Architecture

Two paths, opposite profiles.

DataHashi is a control plane that compiles a Semantic Query to SQL and pushes execution down. The hot path never waits on the warehouse.

Hot path

Sub-second, embedded

User-facing queries are answered from pre-aggregated rollups by an embedded DuckDB engine over Parquet — no warehouse token, no round-trip.

gateway preagg route compile DuckDB · Parquet
≤ 14msp99, served from rollup
Background path

Durable, async builds

Rollups are built and refreshed by durable jobs that do hit the warehouse — poll + push webhook + backstop keep them fresh. No user is waiting.

river queue compile execute scan → Parquet
statelessscale-out nodes, durable queue
Get started

Put one governed model between your data and everything.

Connect a warehouse, bless a model, and start serving sub-second, governed numbers to your LLMs, dashboards, and apps.

No credit card · Bring your own warehouse · Self-serve onboarding