Skip to main content

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:
tursogolibsql-client-gogo-libsql (legacy)
Use caseLocal / embedded database, syncRemote access (over-the-wire)Legacy — embedded replicas
EngineTurso Database (rewrite)libSQL wire protocollibSQL (SQLite fork)
Concurrent writesYes (MVCC)N/A (remote)Not supported
Syncpush/pull (true local-first)Embedded replicas (writes go to remote)
CGONot requiredNot requiredRequired
APIdatabase/sqldatabase/sqldatabase/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.