Schema-aware validation
WaveHouse discovers your ClickHouse schemas via system.columns and validates every ingest against the real schema — unknown fields, type mismatches, and null violations are rejected at the edge.
The open-source real-time API gateway for ClickHouse. Schema-aware ingest, async batching, real-time streaming, and tiered query caching — in a single binary.
connecting to the live stream…
ClickHouse is a phenomenal OLAP database, but pointing a frontend straight at it comes with sharp edges: custom APIs, Kafka queues to avoid “too many parts” errors, replacing-merge logic for deduplication. WaveHouse abstracts all of that into a single, deployable binary so you stop interacting with ClickHouse directly.
If you’re building user-facing analytics, WaveHouse is like Supabase for ClickHouse — or an open-source Tinybird that pushes data to the frontend in real time over SSE, not just via pull-based REST.
Schema-aware validation
WaveHouse discovers your ClickHouse schemas via system.columns and validates every ingest against the real schema — unknown fields, type mismatches, and null violations are rejected at the edge.
Async buffered ingest
Writes land in a durable NATS JetStream WAL and return 200 OK instantly. A background worker batch-flushes to ClickHouse — never drop a packet.
Real-time push
Every event is broadcast to SSE subscribers before it’s flushed to ClickHouse. Gap-fill from JetStream history for late-connecting clients.
In-process query cache
Ristretto cache plus Go singleflight coalesces identical concurrent queries — dashboards survive thundering herds without an extra cache tier to operate.
Hasura-style access control
Per-table, per-role column and row-level policies with JWT claim templating. Stored in NATS KV with file-based bootstrap and cluster sync.
TypeScript SDK
@wavehouse/sdk — zero-dependency client with type-safe query builder, live queries, real-time streaming, and codegen from your schemas.
Plus — optional deduplication (idempotent ingest by ID), a dead-letter queue for failed batch inserts, and Tinybird-style named pipes with parameter binding and per-role restrictions.
The zero-dependency TypeScript SDK wraps the whole surface — typed inserts, a chainable query builder, and live queries that backfill history before streaming:
import { createClient } from '@wavehouse/sdk';
const wh = createClient({ baseURL: 'https://wavehouse.example.com' });
// Returns immediately — buffered in the WAL, schema-validated// at the edge, batch-flushed to ClickHouse behind the scenes.await wh.from('clicks').insert({ page: '/home', button: 'signup' });// Chainable, type-safe, never throws — branch on { data, error }.const { data, error } = await wh.from('clicks') .select('page', 'button', 'score') .where('page', '=', '/home') .orderBy('received_timestamp', 'desc') .limit(100);// Historical backfill + real-time stream, deduplicated at the seam.const lq = wh.from('clicks') .selectAll() .where('page', '=', '/home') .orderBy('received_timestamp', 'desc') .limit(100) .liveQuery({ initial: (result) => setRows(result.data ?? []), next: (event) => addRow(event.data), });
// later: lq.close();One compose file — ClickHouse + WaveHouse — and you have an ingest endpoint, a query endpoint, and a live event stream:
# Boot ClickHouse + WaveHouse with one compose filegit clone https://github.com/Wave-RF/WaveHouse.gitcd WaveHousedocker compose -f deployments/compose/standalone.yaml up -d
# Ingest an event (run Getting Started first to create the `clicks` table; the dev stack ships a trial policy)curl -X POST "http://localhost:8080/v1/ingest?table=clicks" \ -H 'content-type: application/json' \ -d '{"page":"/home","button":"signup","score":42.5}'
# Subscribe to the live streamcurl -N "http://localhost:8080/v1/stream?table=clicks"WaveHouse is fail-closed, so the standalone stack ships a permissive trial policy (a non-admin public role that can read/write the demo tables, seeded on first boot) — then it’s five minutes from git clone to a live event stream. See Getting Started.
How it ships: one wavehouse process — API, batch worker, embedded NATS JetStream, and optional embedded Pebble dedup, all in-process. The only external dependency is ClickHouse. Same binary on a laptop, in Docker, or on a production host.
WaveHouse is alpha — and built entirely in the open.
Apache-2.0-licensed, single binary, no SaaS tier, no vendor lock-in. We ship with honest expectations — see the support cadence and security policy. Kick the tires and tell us where it breaks.