A polyglot Go ORM that generates native query syntax per database.
- Native Query Syntax -- Each driver generates queries in its database's native idiom
- Dual Tag System --
grove:"..." tags with bun:"..." fallback for zero-cost migration
- Near-Raw Performance -- Zero reflection at query time, pooled buffers, cached metadata
- Modular Migrations -- Go-code migrations with multi-module dependency ordering
- Privacy Hooks -- Pre/post query hooks for tenant isolation, PII redaction, and audit logging
- Streaming -- Server-side cursor streaming with per-row hooks
- PostgreSQL -- Native
$1 placeholders, DISTINCT ON, FOR UPDATE, JSONB operators (also compatible with CockroachDB, Neon, Supabase)
- SQLite -- Lightweight embedded database with
INSERT OR REPLACE
- MySQL -- Backtick quoting,
ON DUPLICATE KEY UPDATE, USE INDEX hints (also compatible with TiDB)
- MongoDB -- Native BSON filter documents, aggregation pipelines (also compatible with FerretDB)
- Turso / libSQL -- Distributed SQLite at the edge with embedded replicas and multi-region replication
- ClickHouse -- Columnar OLAP analytics with MergeTree engines, PREWHERE, SAMPLE, and batch inserts
// Create and open the driver, then pass it to Grove
pgdb := pgdriver.New()
pgdb.Open(ctx, "postgres://user:pass@localhost/mydb", driver.WithPoolSize(20))
db, _ := grove.Open(pgdb)
// Access the typed PG query builder via Unwrap
pg := pgdriver.Unwrap(db)
var users []User
err := pg.NewSelect(&users).
Where("email ILIKE $1", "%@example.com").
Where("role = $2", "admin").
OrderExpr("created_at DESC").
Limit(50).
Scan(ctx)
All benchmarks run on SQLite in-memory databases. No external services required.
Run locally: make bench
Benchmarks generated on 2026-02-22 with go1.25.7 on darwin/arm64. Each benchmark ran 5 times; values are averages.
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
4,015 |
880 |
20 |
baseline |
| Grove |
4,381 |
1,283 |
28 |
+9.1% |
| Bun |
8,459 |
5,470 |
27 |
+110.7% |
| GORM |
10,265 |
4,954 |
66 |
+155.7% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
4,747 |
1,096 |
39 |
baseline |
| Grove |
5,575 |
1,458 |
34 |
+17.4% |
| Bun |
6,695 |
5,944 |
43 |
+41.0% |
| GORM |
8,070 |
4,383 |
81 |
+70.0% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
58,079 |
20,984 |
388 |
baseline |
| Grove |
45,686 |
23,413 |
584 |
-21.3% |
| Bun |
67,184 |
23,192 |
395 |
+15.7% |
| GORM |
83,217 |
28,570 |
765 |
+43.3% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
2,821 |
520 |
13 |
baseline |
| Grove |
3,617 |
1,010 |
21 |
+28.2% |
| Bun |
4,074 |
5,205 |
19 |
+44.4% |
| GORM |
5,468 |
4,020 |
49 |
+93.8% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
3,479 |
232 |
8 |
baseline |
| Grove |
5,083 |
553 |
13 |
+46.1% |
| Bun |
5,147 |
4,880 |
12 |
+47.9% |
| GORM |
6,660 |
2,856 |
36 |
+91.4% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
151,006 |
60,141 |
1524 |
baseline |
| Grove |
105,572 |
42,111 |
1421 |
-30.1% |
| Bun |
143,532 |
30,389 |
224 |
-4.9% |
| GORM |
187,914 |
93,706 |
1251 |
+24.4% |
| Library |
ns/op |
B/op |
allocs/op |
vs Raw SQL |
| Raw SQL |
1,401,957 |
605,384 |
16513 |
baseline |
| Grove |
967,190 |
409,753 |
14021 |
-31.0% |
| Bun |
1,359,612 |
408,694 |
2033 |
-3.0% |
| GORM |
1,782,186 |
894,166 |
12051 |
+27.1% |
| Variant |
ns/op |
B/op |
allocs/op |
| Grove |
453 |
864 |
11 |
| Bun |
825 |
1,744 |
17 |
| Variant |
ns/op |
B/op |
allocs/op |
| Grove |
842 |
930 |
19 |
| Bun |
1,012 |
1,425 |
17 |
| Variant |
ns/op |
B/op |
allocs/op |
| Grove |
380 |
736 |
11 |
| Bun |
597 |
1,184 |
14 |
| Variant |
ns/op |
B/op |
allocs/op |
| CacheHit |
11 |
0 |
0 |
| ColdStart |
3,123 |
3,728 |
75 |
| Variant |
ns/op |
B/op |
allocs/op |
| GroveTags |
3,101 |
3,728 |
75 |
| BunFallback |
3,398 |
3,736 |
74 |
Full documentation available in the docs directory.
MIT