Skip to main content
Run a fresh local deployment through this operating loop:
This produces a durable event log and a queryable warehouse snapshot. The examples use curl to show the wire contract. An SDK or any HTTP/1.1 client that can connect to a Unix domain socket can use the same API.

1. Install the binary

Download the versioned archive and checksum from the Groundhog releases. Published archives target Apple Silicon macOS and x86-64 Linux. Each archive contains groundhog, BUILD-INFO, the Groundhog license, and third-party license notices. For version 0.1.0:
Use the version pinned by your application or deployment. The service requires Unix domain sockets and does not open a TCP port.

2. Initialize a deployment

Initialization creates:
The first warehouse is already valid and represents an empty log, so a new deployment is immediately serveable. Initialization publishes groundhog.toml last and is retry-safe: running the same command again validates the deployment and succeeds without rewriting it. Conflicting Groundhog-owned files are refused rather than overwritten, while unrelated siblings in demo/ are preserved. If DIR is omitted, init uses the current directory:
See init for the exact retry and conflict behavior.

3. Review the generated configuration

The generated groundhog.toml is local-first:
Relative paths resolve against the configuration file’s directory, not the process working directory. A deployment can therefore be invoked from anywhere:
mode = "open" is the supported security choice. Operations that would extend or attest history support anchor = "none"; serve, seal, and verify --chain refuse a signed/mirrored/witnessed requirement instead of silently claiming a weaker guarantee. An empty token disables HTTP authentication. To require a bearer token, set one in the file and include it on every request:
The token is stored directly in the configuration file, so protect that file with appropriate filesystem permissions. See the configuration reference for every field and validation rule.

4. Start the service

Run this in one terminal:
The process announces the socket path on standard error as it enters the serving path:
That human lifecycle line is not a readiness protocol. Confirm readiness with a real routed request. The URL host in curl is syntactically required by HTTP/1.1 but ignored by Groundhog, so this guide uses http://ground:
The initial response contains an empty streams array and the genesis warehouse receipt. Stop the service with Ctrl-C or SIGTERM. Graceful shutdown stops admission, lets enqueued mutations reach their real storage outcome, and then releases writer ownership.

5. Ingest an atomic event batch

A successful append returns a durable receipt:
The batch is atomic: Groundhog validates every event before writing any of them. It assigns event IDs, observation times, content hashes, and event hashes.

Retry safely

The pair (source, batch_id) is the durable idempotency key. If a request times out or loses its response, submit the same batch again with the same ID:
  • identical content returns status: "duplicate" and the original event range;
  • different content under the same ID returns HTTP 409 and writes nothing.
Choose a stable batch ID from the source operation, such as a webhook delivery ID, export ID, or sync-run ID. Do not generate a fresh ID merely because a response was lost. The JSON ingest form accepts at most 10,000 events and 32 MiB per batch. The source name system and batch IDs beginning with groundhog/ are reserved for Groundhog.

6. Replay durable history

Replay reads the authoritative log directly, so committed events are visible without publishing the warehouse:
The optional filters are after, source, stream, kind, and limit; all filters are exact matches. The response includes two cursor-like fields with different jobs:
  • last_event_id is the last matching event returned;
  • next_after is how far the scan progressed, including non-matching events.
Persist next_after when polling a filtered subscription. It lets an empty page advance past unrelated history. Each response also reports snapshot_through_event_id, the coherent log frontier captured for that request.

7. Publish the warehouse

Warehouse publication is explicit. Ingest updates the log; it does not automatically refresh SQL relations or the catalog. Leave serve running and execute:
project captures one coherent log snapshot and atomically publishes a complete warehouse. A failed publication never displaces the last good generation. The running server adopts a new generation between requests; an in-flight request stays pinned to the generation it began with. This produces two intentionally different freshness paths: Receipts identify the exact published frontier and make the distinction observable.

8. Query with SQL

The warehouse publishes three queryable relations:
  • events: fixed event columns through the published frontier;
  • meta.streams: source/stream counts, observation times, and kinds; and
  • meta.projection_state: receipt provenance for the generation.
Queries are confined to one read-only SELECT or WITH statement over published relations. File/network access, extensions, mutations, volatile functions, and unsafe engine features are rejected. A truncated result requires a total top-level ORDER BY; the simplest pattern is to order by every selected column or use ORDER BY ALL. Every successful result includes columns, rows, a truncated flag, and a receipt naming the warehouse frontier, chain head, binary build, storage schema, and projection hash.

9. Discover data through the catalog

Narrow the result without SQL:
The catalog lists each published source/stream pair with its event count, first and last observation times, and sorted event kinds. It carries the same snapshot receipt as a query.

10. Verify, seal, and rebuild

Run structural verification:
Recompute payload and event hashes plus the full logical integrity chain:
Verification writes one JSON report to standard output and human diagnostics to standard error. Exit 0 means every requested check passed; exit 3 means verification conclusively found a storage violation. To turn the appendable tail into immutable Parquet segments, stop serve and run:
seal requires writer ownership and therefore cannot run while serve owns that writer. It does not publish the warehouse and does not change logical events, order, IDs, or commitments. To reconstruct the disposable warehouse from the durable log:
rebuild can run while the service is live. It atomically publishes a replacement and subsequent requests adopt it without restarting. Repeated rebuilds of the same frontier produce the same logical relations and receipt; physical DuckDB bytes are not part of that promise.

Common ways to use Groundhog

Record connector output

A connector translates source changes into batches and submits them to POST /v1/events. Use the source’s delivery or sync identity as batch_id. Groundhog owns durable ordering, idempotency, and integrity; the connector retains its source cursor and credentials.

Build a replay consumer

Poll GET /v1/events, filter to the relevant source/stream/kind, and persist next_after. Process business events using immutable event_id values. Each consumer owns its cursor outside Groundhog, so consumers can move independently over the same history.

Analyze a stable snapshot

Run project at a chosen operational boundary, use the catalog to discover streams, and send confined SQL to /v1/query. Retain the returned receipt with reports or agent outputs when you need to identify exactly which history produced them.

Supervise it from an application

An application can launch a pinned groundhog serve child, wait for a successful routed request over the configured socket, use the public HTTP contract, and stop it with SIGTERM. This uses the same data directory and compatibility rules as an operator-managed service.

Current binary capabilities

  • local Unix socket only; no built-in TCP listener;
  • open security mode and local anchor mode none only;
  • JSON batch ingest only; no NDJSON stream or server-local path import;
  • explicit full warehouse publication; no background or incremental refresh;
  • no current.* state relations or deployment-defined projections;
  • JSON query results only; and
  • no CLI ingest, replay, query, or catalog wrappers. Use the HTTP API or an SDK.
Continue with groundhog(1), the HTTP API reference, or deployment operations.