The Complete Go Data Toolkit

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/grove
Grove
ORM
CRDT
KV Store
query.build
native SQL
crdt.sync
converged
kv.get
cache hit
PostgreSQL
MySQL
MongoDB
SQLite
Turso
ClickHouse
Elasticsearch
Drivers

7 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.

PG

PostgreSQL

Native $1 placeholders, JSONB operators, DISTINCT ON, and ILIKE — full Postgres dialect.

postgres.go
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)
MY

MySQL

Backtick quoting, ? placeholders, ON DUPLICATE KEY upserts, and native JSON functions.

mysql.go
my := mysqldriver.Unwrap(db)
 
_, err := my.NewInsert(&User{Name: name, Email: email}).
On("DUPLICATE KEY UPDATE").
Set("`name` = VALUES(`name`)").
Exec(ctx)
MG

MongoDB

Native BSON queries, aggregation pipelines, change streams, and embedded document support.

mongo.go
mg := mongodriver.Unwrap(db)
 
results := mg.NewSelect(&Order{}).
Where("status", "active").
Where("total >", 100).
Sort("-created_at").
Limit(50)
SQ

SQLite

Embedded storage with full SQL and WAL mode

TU

Turso

Edge-replicated SQLite with libSQL

CH

ClickHouse

Columnar analytics with batch inserts

ES

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.

PostgreSQLMySQLMongoDBSQLiteTursoClickHouseElasticsearch
main.go
"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 driver
pgDB, _ := grove.Open(pgdrv)
chDB, _ := grove.Open(chdrv)
Capabilities

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.

model.go
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.

crdt.go
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.

kv.go
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.

multi_db.go
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.

hooks.go
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.

streaming.go
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.

migrations.go
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.

drivers.go
pgdrv := pgdriver.New()
pgdrv.Open(ctx, pgDSN)
pgDB, _ := grove.Open(pgdrv)
 
"text-fd-muted-foreground/60 italic">// Each generates native syntax
pg := 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.

audit.go
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),
})
}
CRDT

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.

Replica A
Replica B
Replica C
Converged
Syncing
crdt.go
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)
cache:
Redis
session:
Badger
config:
DynamoDB
Cache
Sessions
Config
kv.go
store := redis.New(redis.Config{Addr: ":6379"})
 
"text-fd-muted-foreground/60 italic">// Keyspaces for logical separation
cache := kv.WithKeyspace(store, "cache:")
sessions := kv.WithKeyspace(store, "session:")
 
cache.Set(ctx, "user:123", userData, 5*time.Minute)
val, _ := cache.Get(ctx, "user:123")
KV Store

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.

Query Pipeline

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.

Register
query.select
Buildnative SQL
Executedriver
Scanresults
tag.resolved
grove:"..."
query.built
PG Native
result.scanned
Zero-Copy
Cached
Building
Zero-Copy
Error
Developer Experience

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.

PostgreSQL
postgres.go
1package main
2 
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 driver
25 pgdb := pgdriver.New()
26 pgdb.Open(ctx, "postgres:">//user:pass@localhost/mydb")
27 
28 "text-fd-muted-foreground/60 italic">// Pass connected driver to Grove
29 db, _ := grove.Open(pgdb)
30 defer db.Close()
31 
32 "text-fd-muted-foreground/60 italic">// Use typed driver for queries
33 pg := pgdriver.Unwrap(db)
34 var users []User
35 _ = 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}
MongoDB
mongo.go
1package main
2 
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 driver
25 mgdrv := mongodriver.New()
26 mgdrv.Open(ctx, "mongodb:">//localhost:27017/mydb")
27 
28 "text-fd-muted-foreground/60 italic">// Pass connected driver to Grove
29 db, _ := grove.Open(mgdrv)
30 defer db.Close()
31 
32 mgdb := mongodriver.Unwrap(db)
33 var users []User
34 _ = 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