Grove
1.x
Docs/Grove/Turso / libSQL
Open

Reading6 min
Updated31 Jul 2026
Sourcev1/drivers/turso.mdx

The Turso driver provides Grove support for Turso, a distributed SQLite database built on libSQL. It shares the same SQLite dialect and query syntax as the SQLite driver, but connects to Turso's cloud-hosted databases with authentication, embedded replicas, and multi-region replication.

Installation01

go get github.com/xraph/grove
go get github.com/tursodatabase/go-libsql

Connection02

import (
    "context"
    "log"

    "github.com/xraph/grove"
    "github.com/xraph/grove/driver"
    "github.com/xraph/grove/drivers/tursodriver"
    _ "github.com/tursodatabase/go-libsql"
)

// 1. Create and open the driver
tdb := tursodriver.New()
err := tdb.Open(ctx, "libsql://your-db-name-org.turso.io",
    tursodriver.WithAuthToken("your-auth-token"),
)
if err != nil {
    log.Fatal(err)
}

// 2. Pass the connected driver to Grove
db, err := grove.Open(tdb)
if err != nil {
    log.Fatal(err)
}
defer db.Close()

Embedded Replicas

Turso supports embedded replicas -- a local SQLite file that automatically syncs with the remote database. Reads are served from the local copy for sub-millisecond latency, while writes are forwarded to the primary:

tdb := tursodriver.New()
err := tdb.Open(ctx, "libsql://your-db-name-org.turso.io",
    tursodriver.WithAuthToken("your-auth-token"),
    tursodriver.WithEmbeddedReplica("/tmp/local-replica.db"),
    tursodriver.WithSyncInterval(5 * time.Second),
)

Local Development

For local development, point the Turso driver at a regular SQLite file. The driver automatically detects local file paths and uses the SQLite driver:

tdb := tursodriver.New()
err := tdb.Open(ctx, "file:dev.db")

DSN Examples

DSNDescription
"libsql://db-org.turso.io"Turso cloud database
"file:local.db"Local SQLite file (fallback)
":memory:"In-memory database (for tests)

Unwrap Pattern

Use tursodriver.Unwrap to access the underlying *TursoDB from a *grove.DB handle:

tdb := tursodriver.Unwrap(db) // returns *tursodriver.TursoDB

var users []User
tdb.NewSelect(&users).
    Where("email LIKE ?", "%@example.com").
    Scan(ctx)

Turso-Specific Options03

OptionDescription
tursodriver.WithAuthToken(token)Authentication token for Turso cloud
tursodriver.WithEmbeddedReplica(path)Enable embedded replica at local path
tursodriver.WithSyncInterval(d)Sync interval for embedded replicas
driver.WithPoolSize(n)Connection pool size
driver.WithQueryTimeout(d)Default query timeout

Query Syntax04

The Turso driver uses identical SQL syntax to the SQLite driver. All query builders, placeholders, and quoting rules are the same.

Placeholders

tdb.NewSelect(&users).
    Where("email LIKE ?", "%@example.com").
    Where("active = ?", true).
    Scan(ctx)

Type Mapping

Go TypeDatabase Type
boolINTEGER (0/1)
int, int8-int64INTEGER
float32, float64REAL
stringTEXT
time.TimeTEXT (RFC 3339)
[]byteBLOB
map[string]anyTEXT (JSON)

Query Builders05

All query builders work identically to the SQLite driver:

SELECT

tdb := tursodriver.Unwrap(db)

var users []User
tdb.NewSelect(&users).
    Where("role = ?", "admin").
    OrderExpr("created_at DESC").
    Limit(20).
    Scan(ctx)

INSERT

user := User{Name: "Alice", Email: "[email protected]"}
_, err := tdb.NewInsert(&user).Exec(ctx)

// Bulk insert
users := []User{
    {Name: "Alice", Email: "[email protected]"},
    {Name: "Bob", Email: "[email protected]"},
}
_, err := tdb.NewInsert(&users).Exec(ctx)

Upsert

tdb.NewInsert(&user).
    OnConflict("(email) DO UPDATE").
    Set("name = EXCLUDED.name").
    Exec(ctx)

UPDATE

user.Name = "Alice Smith"
_, err := tdb.NewUpdate(&user).WherePK().Exec(ctx)

// Raw SET
_, err := tdb.NewUpdate(&user).
    Set("login_count = login_count + ?", 1).
    Where("id = ?", 42).
    Exec(ctx)

DELETE

_, err := tdb.NewDelete(&user).WherePK().Exec(ctx)

// Soft delete is automatic for models with soft_delete field
// Use ForceDelete() for hard delete
_, err := tdb.NewDelete(&user).WherePK().ForceDelete().Exec(ctx)

RETURNING

SQLite 3.35+ (and Turso/libSQL) support RETURNING:

var id int64
tdb.NewInsert(&user).
    Returning("id").
    Scan(ctx, &id)

Raw Queries

var users []User
tdb.NewRaw("SELECT * FROM users WHERE role = ?", "admin").Scan(ctx, &users)

Transactions06

tdb := tursodriver.Unwrap(db)

tx, err := tdb.BeginTxQuery(ctx, nil)
if err != nil {
    return err
}
defer tx.Rollback()

_, err = tx.NewInsert(&order).Exec(ctx)
if err != nil {
    return err
}

_, err = tx.NewUpdate(&inventory).
    Set("quantity = quantity - ?", order.Quantity).
    Where("product_id = ?", order.ProductID).
    Exec(ctx)
if err != nil {
    return err
}

return tx.Commit()

CREATE TABLE07

_, err := tdb.NewCreateTable((*User)(nil)).
    IfNotExists().
    Exec(ctx)

_, err := tdb.NewCreateTable((*Order)(nil)).
    IfNotExists().
    WithForeignKey("(user_id) REFERENCES users(id) ON DELETE CASCADE").
    Exec(ctx)

Migrations08

The tursomigrate package provides a migration executor compatible with Grove's migration system:

import (
    "github.com/xraph/grove/migrate"
    "github.com/xraph/grove/drivers/tursodriver"
    "github.com/xraph/grove/drivers/tursodriver/tursomigrate"
)

tdb := tursodriver.Unwrap(db)
executor := tursomigrate.New(tdb)
orchestrator := migrate.NewOrchestrator(executor, Migrations)

result, err := orchestrator.Migrate(ctx)

Turso vs SQLite09

FeatureSQLiteTurso
StorageLocal fileCloud-hosted + optional local replica
ReplicationNoneMulti-region
AuthNoneToken-based
Edge deploymentManual file distributionAutomatic replication
Query syntaxIdenticalIdentical
Go drivermodernc.org/sqlitegithub.com/tursodatabase/go-libsql

The Turso driver is ideal when you need SQLite's simplicity with cloud-native distribution, edge deployment, or managed infrastructure.