Documentation Index
Fetch the complete documentation index at: https://docs.turso.tech/llms.txt
Use this file to discover all available pages before exploring further.
Turso offers two Go packages:
| tursogo | libsql-client-go | go-libsql (legacy) |
|---|
| Use case | Local / embedded database, sync | Remote access (over-the-wire) | Legacy — embedded replicas |
| Engine | Turso Database (rewrite) | libSQL wire protocol | libSQL (SQLite fork) |
| Concurrent writes | Yes (MVCC) | N/A (remote) | Not supported |
| Sync | push/pull (true local-first) | — | Embedded replicas (writes go to remote) |
| CGO | Not required | Not required | Required |
| API | database/sql | database/sql | database/sql |
Starting a new project? Use tursogo for local/embedded use or sync. Use libsql-client-go for remote access. Neither requires CGO.
tursogo
For local and embedded use. Built on the Turso Database engine with concurrent writes (MVCC) and async I/O.
Installing
go get turso.tech/database/tursogo
Connecting
import (
"database/sql"
_ "turso.tech/database/tursogo"
)
db, err := sql.Open("turso", "app.db")
In-memory databases are also supported:
db, err := sql.Open("turso", ":memory:")
Querying
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
)`)
_, err = db.Exec("INSERT INTO users (name) VALUES (?)", "Alice")
rows, err := db.Query("SELECT * FROM users")
defer rows.Close()
for rows.Next() {
var id int
var name string
rows.Scan(&id, &name)
fmt.Printf("User: %d %s\n", id, name)
}
Encryption
Encrypt local databases at rest using DSN options:
import (
"database/sql"
"fmt"
_ "turso.tech/database/tursogo"
)
hexkey := "b1bbfda4f589dc9daaf004fe21111e00dc00c98237102f5c7002a5669fc76327"
dsn := fmt.Sprintf("encrypted.db?experimental=encryption&encryption_cipher=aegis256&encryption_hexkey=%s", hexkey)
db, err := sql.Open("turso", dsn)
Supported ciphers: aegis256, aegis256x2, aegis128l, aegis128x2, aegis128x4, aes256gcm, aes128gcm.
Encrypted databases cannot be read as standard SQLite databases — you must use the Turso Database engine to open them.
Turso Cloud databases can also be encrypted with bring-your-own-key — learn more.
Sync (Push and Pull)
For local database with cloud sync. All reads and writes happen locally; use Push() to send changes to the cloud and Pull() to fetch remote changes.
import (
"context"
"os"
turso "turso.tech/database/tursogo"
)
ctx := context.Background()
syncDb, err := turso.NewTursoSyncDb(ctx, turso.TursoSyncDbConfig{
Path: "app.db",
RemoteUrl: os.Getenv("TURSO_DATABASE_URL"),
AuthToken: os.Getenv("TURSO_AUTH_TOKEN"),
})
db, err := syncDb.Connect(ctx)
On the first run, the local database is automatically bootstrapped from the remote. See Turso Sync for full details.
Push and Pull
// Push local writes to Turso Cloud
err := syncDb.Push(ctx)
// Pull remote changes to local database
changed, err := syncDb.Pull(ctx)
Checkpoint
Compact the local WAL to bound disk usage while preserving sync state:
err := syncDb.Checkpoint(ctx)
Stats
stats, err := syncDb.Stats(ctx)
fmt.Printf("CDC operations: %d\n", stats.CdcOperations)
fmt.Printf("Main WAL size: %d\n", stats.MainWalSize)
fmt.Printf("Network sent: %d bytes\n", stats.NetworkSentBytes)
fmt.Printf("Network received: %d bytes\n", stats.NetworkReceivedBytes)
fmt.Printf("Last pull: %d\n", stats.LastPullUnixTime)
fmt.Printf("Last push: %d\n", stats.LastPushUnixTime)
fmt.Printf("Revision: %s\n", stats.Revision)
libsql-client-go (Remote)
The recommended package for any application that connects to a remote Turso Cloud database over the network — web servers, Docker containers, serverless functions. Pure Go, no native dependencies.
Installing
go get github.com/tursodatabase/libsql-client-go/libsql
Connecting
import (
"database/sql"
"os"
_ "github.com/tursodatabase/libsql-client-go/libsql"
)
url := os.Getenv("TURSO_DATABASE_URL") + "?authToken=" + os.Getenv("TURSO_AUTH_TOKEN")
db, err := sql.Open("libsql", url)
Querying
Uses the standard database/sql interface — same as tursogo:
rows, err := db.Query("SELECT * FROM users WHERE id = ?", 1)
go-libsql (Legacy)
The go-libsql package is built on libSQL, our open-source fork of SQLite that predated the Turso Database engine. It is fully supported — if you run into something that doesn’t work yet with tursogo, go-libsql is a reliable fallback.
With go-libsql embedded replicas, reads are local but writes go to the remote database. For true local-first writes with push/pull sync, use tursogo with NewTursoSyncDb — see the quickstart.
Embedded Replicas
For new projects, we recommend tursogo with NewTursoSyncDb for sync use cases — it is built on the Turso Database engine with better performance, true local-first writes, and concurrent write support.
You can work with embedded replicas that can sync from the remote database to a local SQLite file, and delegate writes to the remote primary database:
package main
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"github.com/tursodatabase/go-libsql"
)
func main() {
dbName := "local.db"
primaryUrl := "libsql://[DATABASE].turso.io"
authToken := "..."
dir, err := os.MkdirTemp("", "libsql-*")
if err != nil {
fmt.Println("Error creating temporary directory:", err)
os.Exit(1)
}
defer os.RemoveAll(dir)
dbPath := filepath.Join(dir, dbName)
connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
libsql.WithAuthToken(authToken)
)
if err != nil {
fmt.Println("Error creating connector:", err)
os.Exit(1)
}
defer connector.Close()
db := sql.OpenDB(connector)
defer db.Close()
}
Embedded Replicas only works where you have access to the file system.
Manual Sync
if err := connector.Sync(); err != nil {
fmt.Println("Error syncing database:", err)
}
Periodic Sync
syncInterval := time.Minute
connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
libsql.WithAuthToken(authToken),
libsql.WithSyncInterval(syncInterval),
)
Read Your Writes
By default, after a sync the server must fully catch up with your changes before returning — guaranteeing you always read your own writes. This is safer but much slower, since the server must process all pending changes. If you can tolerate eventually-consistent reads, disable this for significantly faster syncs:
connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
libsql.WithAuthToken(authToken),
libsql.WithReadYourWrites(false),
)
Encryption
For new projects, we recommend tursogo for local encryption — it is built on the Turso Database engine with better performance and concurrent write support.
To enable encryption on a SQLite file, pass the encryption key value as an argument to the constructor:
encryptionKey := "SuperSecretKey"
connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
libsql.WithAuthToken(authToken),
libsql.WithEncryption(encryptionKey),
)
Encrypted databases appear as raw data and cannot be read as standard SQLite databases. You must use the libSQL client for any operations — learn more.