Fabriq
1.x
Docs/Fabriq/Configuration
Open

Reading7 min
Updated2 Aug 2026
Sourcev1/(getting-started)/configuration.mdx

Fabriq takes its configuration two ways: library code passes a fabriq.Config value (plus functional Options) to fabriq.Open, and the fabriq binary loads the same shape through Forge's config manager — a config.yaml file plus FABRIQ_* environment overrides. This page is task-oriented — the exhaustive field-by-field reference lives at Reference: Configuration.

The Config shape01

fabriq.Config declares which stores exist and which projections run. Entities are not configured here — they are registered in code through the registry.

type Config struct {
	Postgres      PostgresConfig      // DSN required (single-shard): the source of truth
	Shards        []ShardConfig       // optional: shard the source of truth by tenant
	Redis         RedisConfig         // event fan-out; required for subscriptions + projections
	FalkorDB      FalkorDBConfig      // graph projection engine
	Elasticsearch ElasticsearchConfig // search projection engine
	Storage       StorageConfig       // blob/CAS byte plane (file-plane storage)
	Projections   ProjectionsConfig   // Graph/Search on-off toggles
	Subscriptions SubscriptionsConfig // delta-plane tuning
	Cache         CacheConfig         // engine cache (result-set caching at Repo[T])
	Encryption    EncryptionConfig    // at-rest encryption for blob-source credentials
}

Postgres is the only required store. PostgresConfig.DSN must be set; PostgresConfig.PoolSize is optional. Everything else is opt-in and degrades to a typed ErrStoreNotConfigured when absent. To scale the source of truth across multiple Postgres instances, set Shards in place of Postgres — a single Postgres block is the one-shard case. See Sharding.

The subscription plane is tuned through three fields:

type SubscriptionsConfig struct {
	ConflationWindow time.Duration // hub last-write-wins flush window (default 150ms)
	StreamMaxLen     int64         // approximate MAXLEN per Redis change channel (default 500)
	SubscribeBuffer  int           // per-subscriber delta buffer (default 64)
}

Library vs binary

go
f, stores, err := fabriq.Open(ctx, reg, fabriq.Config{
	Postgres: fabriq.PostgresConfig{
		DSN:      "postgres://user:pass@pg:5432/fabriq?sslmode=disable",
		PoolSize: 16,
	},
	Redis: fabriq.RedisConfig{Addr: "redis:6379"},

	// Turn projections on only when their backing store is configured.
	FalkorDB:      fabriq.FalkorDBConfig{Addr: "falkordb:6379"},
	Elasticsearch: fabriq.ElasticsearchConfig{Addrs: []string{"http://es:9200"}},
	Projections:   fabriq.ProjectionsConfig{Graph: true, Search: true},

	Subscriptions: fabriq.SubscriptionsConfig{
		ConflationWindow: 200 * time.Millisecond,
		StreamMaxLen:     1000,
		SubscribeBuffer:  128,
	},
})

Functional options02

Pass Option values after the Config to fabriq.Open (or fabriq.New). These come from options.go:

f, stores, err := fabriq.Open(ctx, reg, cfg,
	fabriq.WithConflationWindow(200*time.Millisecond),
	fabriq.WithSubscribeBuffer(128),
	fabriq.WithStreamMaxLen(1000),
	fabriq.WithWaitPollInterval(25*time.Millisecond),
	fabriq.WithUpcasters(chain),
	fabriq.WithAuthz(authzFn),
	fabriq.WithDocumentAuthz(docAuthzFn),
)

The full set:

  • WithConflationWindow(d time.Duration) — the hub's last-write-wins flush window (spec range 100–250ms; default 150ms).

  • WithSubscribeBuffer(n int) — per-subscriber delta buffer (default 64). A full buffer drops; clients refetch and resume by Last-Event-ID.

  • WithStreamMaxLen(n int64) — approximate MAXLEN for per-channel Redis streams, i.e. catch-up depth before clients must refetch (default 500).

  • WithWaitPollInterval(d time.Duration) — poll cadence for WaitForProjection (default 25ms).

  • WithAuthz(fn subscribe.AuthzFunc) — the subscribe-time authorization hook, consulted when resolving a SubscribeScope to a channel.

  • WithDocumentAuthz(fn func(ctx context.Context, docID string) error) — the document-plane authorization hook, consulted for both ApplyUpdate (writes) and SubscribeDocument (reads). Without it, any authenticated member of the tenant may touch any of the tenant's documents.

  • WithUpcasters(chain *event.UpcasterChain) — registers the event payload upcaster chain. Projection engines apply it at decode, so appliers only ever see the latest payload shape.

  • WithTraceparent(fn func(context.Context) string) — supplies the W3C traceparent extractor stamped into event envelopes. Open already installs the production extractor by default, so override only for custom propagation.

  • WithClock(now func() time.Time) — overrides the command-plane clock (tests).

Config derives some options for you

Config.Options() translates the Subscriptions block into the matching options, so a value you set on Config and the equivalent option are interchangeable:

func (c Config) Options() []Option {
	var opts []Option
	if c.Subscriptions.ConflationWindow > 0 {
		opts = append(opts, WithConflationWindow(c.Subscriptions.ConflationWindow))
	}
	if c.Subscriptions.StreamMaxLen > 0 {
		opts = append(opts, WithStreamMaxLen(c.Subscriptions.StreamMaxLen))
	}
	if c.Subscriptions.SubscribeBuffer > 0 {
		opts = append(opts, WithSubscribeBuffer(c.Subscriptions.SubscribeBuffer))
	}
	return opts
}

Open prepends cfg.Options() to the explicit options you pass, so an explicit option wins on a later duplicate. Use Config for declarative deployment values; use options for behaviors with no config field (authz hooks, upcasters, clock).

Environment variables03

Forge's config manager reads these, overlaying them on any config.yaml (env wins). --dsn is a global flag that overrides FABRIQ_POSTGRES_DSN for ad-hoc operator commands.

VariableRequiredDefaultPurpose
FABRIQ_POSTGRES_DSNto servePostgres DSN; the source of truth. Overridable with --dsn.
FABRIQ_REDIS_ADDRto serveRedis address for the event stream and subscriptions.
FABRIQ_FALKORDB_ADDRnoFalkorDB address; enables the graph projection.
FABRIQ_ELASTICSEARCH_ADDRSnoComma-separated Elasticsearch addresses; enables the search projection.
FABRIQ_HTTP_ADDRno:8081Worker HTTP listen address (health, metrics).
FABRIQ_RECONCILE_INTERVALnoReconciliation cadence as a Go duration; "0" disables it.
Note

The operator commands (migrate, inspect, rebuild, reconcile) open their own stores from --dsn/FABRIQ_POSTGRES_DSN and never serve. Only fabriq serve connects the full worker plane. See CLI.

Validation04

Config.Validate() runs cross-field checks before Open dials anything — it never opens a connection. It enforces:

  • postgres.dsn is set (the source of truth).

  • If projections.graph is on, falkordb.addr is non-empty.

  • If projections.search is on, elasticsearch.addrs is non-empty.

  • If either projection is on, redis.addr is set (projections need the event stream).

  • subscriptions.conflation_window is >= 0.

A failed check returns a descriptive error and Open aborts before touching the network, so a misconfiguration surfaces at startup rather than on the first request.

Next steps05