Installation
Prerequisites, getting the module, and the migrate-then-serve startup order for a Fabriq service.
Fabriq is both a Go library you import (github.com/xraph/fabriq) and a single binary (fabriq) that runs the background worker plane and the operator commands. This page covers what you need installed, how to pull the module, and the order to bring a service up.
Prerequisites
- Go 1.25.7 or newer. The module declares
go 1.25.7ingo.mod. The hermetic Docker build (below) uses thegolang:1.26toolchain image. - PostgreSQL — the source of truth. The command store, relational/timeseries/vector ports, and projection bookkeeping all live here, so Postgres is the one store Fabriq cannot run without.
- TimescaleDB extension for hypertable telemetry (the
TSQuerierbulk-write path). - pgvector extension for the embedding port (
VectorQuerier, HNSW similarity search). - Both extensions degrade gracefully when absent: a Postgres without them still serves commands, relational reads, projections, and subscriptions. Only the timeseries and vector planes require them.
- TimescaleDB extension for hypertable telemetry (the
- Redis — required for live subscriptions and for running projections. The outbox relay publishes change channels to Redis Streams; the subscription hub tails them. Without Redis, commands and relational reads still work, but
Subscribeand the graph/search projections do not.
Optional, enabled per data plane:
- FalkorDB — backs the graph projection (
GraphQuerier, openCypher). Without it,Graph()returns a not-configured port. - Elasticsearch — backs the search projection (
SearchQuerier). Without it,Search()returns a not-configured port.
Every optional store degrades to a typed ErrStoreNotConfigured rather than a nil panic. A minimal deployment is Postgres plus Redis; add FalkorDB and Elasticsearch only when you turn on the graph and search projections. See Configuration for the toggles.
Getting the module
go get github.com/xraph/fabriqTo install the operator and worker binary:
go install github.com/xraph/fabriq/cmd/fabriq@latestThe grove replace caveat
go.mod carries local replace directives pointing at out-of-tree grove checkouts:
replace github.com/xraph/grove => ../../xraph/forgery/grove
replace github.com/xraph/grove/drivers/pgdriver => ../../xraph/forgery/grove/drivers/pgdriverThese exist until grove cuts a tagged release. They resolve fine inside the development checkout layout but not for an arbitrary go build elsewhere. Hermetic Docker builds avoid the problem by vendoring first: make docker-build runs go mod vendor, then the Dockerfile builds with GOFLAGS=-mod=vendor and needs no network and no out-of-tree paths. Vendoring stays harmless once the replaces are dropped, so the same build path keeps working after grove is tagged.
First steps
Bring a service up in two distinct phases: apply migrations once as an operator step, then start serving. Never fold schema migration into request-path startup.
Apply migrations. Run grove's migrations against the database before anything serves. This is advisory-locked, so it is safe to run from a one-shot Job even with multiple replicas waiting.
fabriq migrate up --dsn "postgres://user:pass@localhost:5432/fabriq?sslmode=disable"The DSN can also come from FABRIQ_POSTGRES_DSN; --dsn overrides it. See Migrations for the full up/down/status workflow.
Register your domain and assemble the facade. In library code, build a registry, register an entity pack, then call fabriq.Open. Postgres is mandatory; Redis is what turns on subscriptions and projections.
package main
import (
"context"
"log"
"github.com/xraph/fabriq"
"github.com/xraph/fabriq/core/registry"
"github.com/xraph/fabriq/domain"
)
func main() {
reg := registry.New()
if err := domain.RegisterAll(reg); err != nil {
log.Fatalf("register domain: %v", err)
}
f, stores, err := fabriq.Open(context.Background(), reg, fabriq.Config{
Postgres: fabriq.PostgresConfig{DSN: "postgres://user:pass@localhost:5432/fabriq?sslmode=disable"},
Redis: fabriq.RedisConfig{Addr: "localhost:6379"},
})
if err != nil {
log.Fatalf("open fabriq: %v", err)
}
defer f.Close()
_ = stores // worker-plane wiring (relay, electors, projection consumers)
}Open returns the *fabriq.Fabriq facade application code holds, plus a *fabriq.Stores handle the worker plane uses for relay, leader election, and projection consumers. Application services hold only the facade.
domain.RegisterAll registers the example domain pack (site, asset, tag, page). To model your own entities, register your own registry.EntitySpec set against a fresh registry.New() instead.
Next steps
Introduction
Fabriq is a standalone data fabric for Go — the single module through which application code talks to every datastore, enforcing tenancy, eventing, and projection invariants across all of them.
Quickstart
Build a registry, open the facade, run create and update commands under a tenant context, read back, batch, and subscribe to deltas.