Own your data layer
Polyglot ORM with native query syntax, offline-first CRDT sync, universal KV store, and privacy hooks — across 7 database drivers. Part of the Forge ecosystem.
go get github.com/xraph/grove7 databases. One API.
Each driver generates its database's native query syntax. PostgreSQL uses $1 placeholders, MySQL uses ?, MongoDB uses native BSON — no unified DSL compromising performance.
PostgreSQL
Native $1 placeholders, JSONB operators, DISTINCT ON, and ILIKE — full Postgres dialect.
pg := pgdriver.Unwrap(db) users := pg.NewSelect(&User{}). Where("email ILIKE $1", "%@acme.com"). Where("metadata->>'role' = $2", "admin"). OrderExpr("created_at DESC"). Limit(20)MySQL
Backtick quoting, ? placeholders, ON DUPLICATE KEY upserts, and native JSON functions.
my := mysqldriver.Unwrap(db) _, err := my.NewInsert(&User{Name: name, Email: email}). On("DUPLICATE KEY UPDATE"). Set("`name` = VALUES(`name`)"). Exec(ctx)MongoDB
Native BSON queries, aggregation pipelines, change streams, and embedded document support.
mg := mongodriver.Unwrap(db) results := mg.NewSelect(&Order{}). Where("status", "active"). Where("total >", 100). Sort("-created_at"). Limit(50)SQLite
Embedded storage with full SQL and WAL mode
Turso
Edge-replicated SQLite with libSQL
ClickHouse
Columnar analytics with batch inserts
Elasticsearch
Full-text search with JSON DSL
One API
Every driver plugs into the same grove.Open(drv) interface. Switch from PostgreSQL to ClickHouse without changing application code. Models, hooks, and migrations compose across all 7 drivers.
"text-fd-muted-foreground/60 italic">// One interface. Any driver. Zero changes.pgdrv := pgdriver.New()pgdrv.Open(ctx, "postgres:">//localhost/app") chdrv := chdriver.New()chdrv.Open(ctx, "clickhouse:">//localhost/analytics") "text-fd-muted-foreground/60 italic">// Same grove.Open — native syntax per driverpgDB, _ := grove.Open(pgdrv)chDB, _ := grove.Open(chdrv)Everything you need for data
ORM, CRDT, key-value store, streaming, hooks, and migrations — Grove is a complete data toolkit for Go applications.
Polyglot ORM
Native query syntax per database with dual grove/bun tag system. Zero-reflection hot path, cached field offsets, and pooled buffers for near-raw performance.
type User struct { grove.BaseModel `grove:"table:users,alias:u"` ID int64 `grove:"id,pk,autoincrement"` Name string `grove:"name,notnull"` Email string `grove:"email,notnull,unique"` SSN string `grove:"ssn,privacy:pii"`}Offline-First CRDT
LWW-Register, PN-Counter, and OR-Set types with automatic conflict resolution. Distributed nodes modify data independently and converge without coordination.
plugin := crdt.NewPlugin(crdt.PluginConfig{ NodeID: "node-1", Tombstone: true,})plugin.Register("documents", crdt.LWWRegister)plugin.Register("likes", crdt.PNCounter)plugin.Register("tags", crdt.ORSet)Universal KV Store
5 backends — Redis, Memcached, DynamoDB, BoltDB, and Badger. Keyspaces for logical separation, composable middleware for logging, metrics, and circuit breakers.
store := redis.New(redis.Config{Addr: ":6379"})cache := kv.WithKeyspace(store, "cache:")sessions := kv.WithKeyspace(store, "session:") cache.Set(ctx, "user:123", data, 5*time.Minute)val, _ := cache.Get(ctx, "user:123")Multi-Database
Named database connections with DBManager and vessel DI. Connect PostgreSQL, ClickHouse, and SQLite in a single app with per-DB hooks and migrations.
ext := extension.New( extension.WithDatabase("primary", pgDrv), extension.WithDatabase("analytics", chDrv), extension.WithDefaultDatabase("primary"),)Privacy Hooks
Hook interfaces run before every query and mutation. Inject tenant isolation, redact PII fields, or log to audit trails without authorization logic in the ORM.
func (t *TenantIsolation) BeforeQuery( ctx context.Context, qc *hook.QueryContext,) (*hook.HookResult, error) { return &hook.HookResult{ Decision: hook.Modify, Filters: []hook.ExtraFilter{ {Clause: "tenant_id = $1", Args: []any{tid}}, }, }, nil}Streaming & CDC
Stream[T] is a lazy, pull-based generic iterator. Composable pipeline transforms (Map, Filter, Chunk, Reduce) and Go 1.23+ range-over-func. ChangeStream adds CDC.
s, _ := pgdb.NewSelect(&User{}). Where("active = $1", true).Stream(ctx)defer s.Close() active := stream.Filter(s, func(u User) bool { return u.Email != ""})names := stream.Map(active, func(u User) (string, error) { return u.Name, nil})Modular Migrations
Go-code migrations with dependency-aware ordering. Forge extensions ship their own migrations that compose automatically across modules.
var Migrations = migrate.NewGroup("forge.billing", migrate.DependsOn("core"),)Migrations.MustRegister(&migrate.Migration{ Name: "create_invoices", Version: "20240201000000", Up: createInvoicesUp, Down: createInvoicesDown,})7 Database Drivers
PostgreSQL, MySQL, SQLite, MongoDB, Turso, ClickHouse, and Elasticsearch. Each generates native syntax while sharing the model registry and hook engine.
pgdrv := pgdriver.New()pgdrv.Open(ctx, pgDSN)pgDB, _ := grove.Open(pgdrv) "text-fd-muted-foreground/60 italic">// Each generates native syntaxpg := pgdriver.Unwrap(pgDB)pg.NewSelect(&users).Where("email ILIKE $1", p)Observability
Prometheus metrics, distributed tracing, and audit trail hooks. Track query latency, row counts, and log every mutation for compliance.
func (a *AuditHook) AfterMutation( ctx context.Context, model any, oldVal, newVal any,) error { return a.chronicle.Log(ctx, chronicle.Entry{ Action: "update", Table: "users", UserID: auth.UserID(ctx), })}Offline-first by design.
Conflict-Free Replicated Data Types let distributed nodes modify data independently and converge automatically — no coordination required.
LWW-Register
Last-Writer-Wins for simple fields. Automatic conflict resolution using logical timestamps across replicas.
PN-Counter
Distributed counters that always converge. Increment and decrement independently on any node.
OR-Set
Observed-Remove sets that handle concurrent add/remove operations across replicas without conflicts.
plugin := crdt.NewPlugin(crdt.PluginConfig{ NodeID: "node-1", Tombstone: true,})plugin.Register("documents", crdt.LWWRegister)plugin.Register("likes", crdt.PNCounter)plugin.Register("tags", crdt.ORSet)store := redis.New(redis.Config{Addr: ":6379"}) "text-fd-muted-foreground/60 italic">// Keyspaces for logical separationcache := kv.WithKeyspace(store, "cache:")sessions := kv.WithKeyspace(store, "session:") cache.Set(ctx, "user:123", userData, 5*time.Minute)val, _ := cache.Get(ctx, "user:123")Universal key-value storage.
One interface, five production-grade backends. Swap between Redis, Memcached, DynamoDB, BoltDB, and Badger without changing application code.
5 Backends
Redis, Memcached, DynamoDB, BoltDB, and Badger — swap implementations anytime without code changes.
Keyspaces
Logical namespaces within a single store. Prefix-based isolation keeps cache, sessions, and config separated.
Middleware
Composable middleware for logging, metrics, circuit breakers, and caching layers. Stack them as needed.
From model to result.
Grove orchestrates the entire query lifecycle — tag resolution, query building, hook evaluation, execution, and result scanning.
Reflect Once, Query Fast
Model metadata is cached at registration time using sync.Map. The hot query path has zero reflection — just cached offsets and pooled byte buffers.
Native Syntax Per Driver
Each driver generates its database's native query language. PostgreSQL uses $1 placeholders, MySQL uses ?, and MongoDB uses native BSON filter documents.
Privacy Hook Chain
Hooks run before and after every query. Inject tenant isolation WHERE clauses, redact PII fields from results, or log mutations to Chronicle for audit trails.
Native syntax. Maximum performance.
Write PostgreSQL queries that read like PostgreSQL and MongoDB queries that read like MongoDB. Grove respects each database's native idioms.
1package main2 3import (4 "context"5 "fmt"6 7 "github.com/xraph/grove"8 "github.com/xraph/grove/drivers/pgdriver"9)10 11type User struct {12 grove.BaseModel `grove:"table:users,alias:u"`13 14 ID int64 `grove:"id,pk,autoincrement"`15 Name string `grove:"name,notnull"`16 Email string `grove:"email,notnull,unique"`17 Role string `grove:"role,default:'user'"`18 Metadata JSONMap `grove:"metadata,type:jsonb"`19}20 21func main() {22 ctx := context.Background()23 24 "text-fd-muted-foreground/60 italic">// Create and open the driver25 pgdb := pgdriver.New()26 pgdb.Open(ctx, "postgres:">//user:pass@localhost/mydb")27 28 "text-fd-muted-foreground/60 italic">// Pass connected driver to Grove29 db, _ := grove.Open(pgdb)30 defer db.Close()31 32 "text-fd-muted-foreground/60 italic">// Use typed driver for queries33 pg := pgdriver.Unwrap(db)34 var users []User35 _ = pg.NewSelect(&users).36 Where("email ILIKE $1", "%@example.com").37 Where("metadata->>'tier' = $2", "premium").38 DistinctOn("email").39 OrderExpr("email, created_at DESC").40 Limit(50).41 Scan(ctx)42 fmt.Printf("found %d users\n", len(users))43}1package main2 3import (4 "context"5 "fmt"6 7 "github.com/xraph/grove"8 "github.com/xraph/grove/drivers/mongodriver"9 "go.mongodb.org/mongo-driver/bson"10)11 12type User struct {13 grove.BaseModel `grove:"table:users"`14 15 ID string `grove:"_id,pk"`16 Name string `grove:"name,notnull"`17 Email string `grove:"email,notnull,unique"`18 Role string `grove:"role"`19}20 21func main() {22 ctx := context.Background()23 24 "text-fd-muted-foreground/60 italic">// Create and open the driver25 mgdrv := mongodriver.New()26 mgdrv.Open(ctx, "mongodb:">//localhost:27017/mydb")27 28 "text-fd-muted-foreground/60 italic">// Pass connected driver to Grove29 db, _ := grove.Open(mgdrv)30 defer db.Close()31 32 mgdb := mongodriver.Unwrap(db)33 var users []User34 _ = mgdb.NewFind(&users).35 Filter(bson.M{36 "email": bson.M{"$regex": "@example.com$"},37 "role": bson.M{"$in": bson.A{"admin", "mod"}},38 }).39 Sort(bson.D{{"email", 1}, {"created_at", -1}}).40 Limit(50).41 Scan(ctx)42 fmt.Printf("found %d users\n", len(users))43}Build data-intensive Go apps
Polyglot ORM, offline-first CRDT sync, universal KV store, and privacy hooks across 7 database drivers. Add Grove to your Go service in minutes.
go get github.com/xraph/grove