# How to Use Turso with Go: Complete Guide to the tursogo Database Driver

> Learn to use Turso with Go using the tursogo driver. This guide shows how to connect to Turso databases locally or in the cloud with `database/sql` compatibility.

- Repository: [Turso Database/turso](https://github.com/tursodatabase/turso)
- Tags: how-to-guide
- Published: 2026-06-22

---

**The tursogo driver implements the standard `database/sql` interface, allowing you to connect to Turso databases in Go by importing `turso.tech/database/tursogo` and using `sql.Open("turso", dsn)` for local files or `turso.NewTursoSyncDb()` for cloud-synced instances.**

The `tursogo` package in the `tursodatabase/turso` repository provides native Go support for Turso's SQLite-compatible databases. It implements the standard `database/sql` driver interface, meaning any code that works with `database/sql` works with Turso without modification, while also offering advanced synchronization features for edge computing scenarios.

## Driver Architecture and Core Components

The tursogo driver bridges Go's standard database abstraction with Turso's native C API, supporting both standalone local databases and synchronized edge replicas.

### Driver Registration and Initialization

In [`bindings/go/driver_db.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/driver_db.go) lines 70-73, the driver registers itself with Go's database/sql package via `sql.Register("turso", &tursoDbDriver{})`. This registration happens automatically when you import the package.

The `InitLibrary` function in [`bindings/go/bindings.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/bindings.go) lines 10-21 handles one-time loading of the platform-specific native library, ensuring thread-safe initialization exactly once per process.

### Connection Lifecycle

When you call `sql.Open("turso", dsn)`, the driver's `Open` method (implemented in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) lines 90-129) performs several critical operations:

1. Parses the DSN using `parseDSN` (lines 219-255 in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go))
2. Invokes `InitLibrary` to load native bindings
3. Creates the underlying database via `turso_database_new`
4. Establishes a connection via `turso_database_connect`
5. Applies the busy-timeout if specified in the DSN

The `tursoDbConnection` struct (lines 131-200 in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go)) implements `driver.Conn`, `driver.ExecerContext`, and `driver.QueryerContext`, translating standard SQL calls to Turso's low-level C API through wrappers like `turso_statement_bind_positional_*` and `turso_statement_step`.

### Synced Database Architecture

For edge-sync scenarios, the driver provides `TursoSyncDb` in [`bindings/go/driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/driver_sync.go). This high-level wrapper manages:

- **Push/pull replication** with Turso Cloud
- **Checkpointing** of the write-ahead log
- **Automatic IO processing** via an `extraIo` hook

The `tursoSyncConnector.Connect` method (lines 99-106 in [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go)) attaches the `processOneIo` callback, allowing the SQL executor to interleave network and file IO while stepping statements.

## Basic Usage: Local SQLite Databases

For standalone local databases without cloud synchronization, use the standard `database/sql` workflow:

```go
package main

import (
	"database/sql"
	"log"

	_ "turso.tech/database/tursogo" // registers the "turso" driver
)

func main() {
	// DSN: path to the SQLite file + optional query params (e.g. _busy_timeout=5000)
	db, err := sql.Open("turso", "example.db?_busy_timeout=5000")
	if err != nil {
		log.Fatalf("open: %v", err)
	}
	defer db.Close()

	// Create a table
	_, err = db.Exec(`
		CREATE TABLE IF NOT EXISTS items (
			id   INTEGER PRIMARY KEY AUTOINCREMENT,
			name TEXT NOT NULL
		)
	`)
	if err != nil {
		log.Fatalf("create: %v", err)
	}

	// Insert a row
	res, err := db.Exec(`INSERT INTO items (name) VALUES (?)`, "hello")
	if err != nil {
		log.Fatalf("insert: %v", err)
	}
	id, _ := res.LastInsertId()
	log.Printf("inserted row id=%d", id)

	// Query back
	var name string
	row := db.QueryRow(`SELECT name FROM items WHERE id = ?`, id)
	if err := row.Scan(&name); err != nil {
		log.Fatalf("query: %v", err)
	}
	log.Printf("retrieved name=%s", name)
}

```

The driver handles all statement preparation and execution through `tursoDbStatement` and `tursoDbConnection` (see [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) lines 131-200), translating your Go SQL calls to native Turso operations.

## Advanced Usage: Synced Databases with Turso Cloud

For applications requiring synchronization between local storage and Turso Cloud, use `NewTursoSyncDb`:

```go
package main

import (
	"context"
	"database/sql"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	turso "turso.tech/database/tursogo"
)

func main() {
	// Required env vars – see the example in the repo (examples/go/sync/sync.go)
	remoteURL := os.Getenv("TURSO_DATABASE_URL")
	authToken := os.Getenv("TURSO_AUTH_TOKEN")
	if remoteURL == "" || authToken == "" {
		log.Fatal("TURSO_DATABASE_URL and TURSO_AUTH_TOKEN must be set")
	}

	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()

	// Build a synced DB wrapper
	syncDB, err := turso.NewTursoSyncDb(ctx, turso.TursoSyncDbConfig{
		Path:      "local.db",    // local file
		RemoteUrl: remoteURL,    // libsql://… or https://…
		AuthToken: authToken,
	})
	if err != nil {
		log.Fatalf("NewTursoSyncDb: %v", err)
	}
	defer syncDB.Checkpoint(ctx) // optional final checkpoint

	// Obtain a *sql.DB that uses the sync connector
	db, err := syncDB.Connect(ctx)
	if err != nil {
		log.Fatalf("Connect: %v", err)
	}
	defer db.Close()

	// Normal SQL usage …
	_, err = db.Exec(`CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, msg TEXT, ts INTEGER)`)
	if err != nil {
		log.Fatalf("create table: %v", err)
	}
	_, err = db.Exec(`INSERT INTO events (msg, ts) VALUES (?, ?)`, "first", time.Now().Unix())
	if err != nil {
		log.Fatalf("insert: %v", err)
	}

	// Periodically push local changes and pull remote ones
	go func() {
		tick := time.NewTicker(60 * time.Second)
		for {
			select {
			case <-ctx.Done():
				return
			case <-tick.C:
				if err := syncDB.Push(ctx); err != nil {
					log.Printf("[push] error: %v", err)
				}
				changed, err := syncDB.Pull(ctx)
				if err != nil {
					log.Printf("[pull] error: %v", err)
				} else if changed {
					log.Println("[pull] applied remote changes")
				}
			}
		}
	}()

	<-ctx.Done()
	log.Println("shutting down")
}

```

The `NewTursoSyncDb` function (lines 14-44 in [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go)) creates the underlying sync engine via `turso_sync_database_new`, parses the DSN using `parseSyncDSN` (lines 111-132), and sets up the IO processing queue. The `Connect` method returns a standard `*sql.DB` backed by `tursoSyncConnector`, which handles `driveOpUntilDone` and `processIoQueue` internally.

## Configuration and DSN Options

### DSN Parameters

The driver parses Data Source Names in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) lines 219-255 via `parseDSN`. Key parameters include:

- **`_busy_timeout`**: Duration in milliseconds the database waits before returning a `SQLITE_BUSY` error
- **File path**: The local SQLite database file location

For synced databases, `parseSyncDSN` (lines 111-132 in [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go)) handles additional authentication parameters.

### Using the Connector API

For explicit configuration, use `NewConnector` to create a `TursoConnector` (lines 44-74 in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go)):

```go
import (
	"context"
	"database/sql"

	_ "turso.tech/database/tursogo"
	"turso.tech/database/tursogo"
)

func main() {
	// Use the connector API to set a 10‑second busy timeout
	connector, _ := turso.NewConnector(
		"mydb.db?_busy_timeout=10000",
		turso.WithBusyTimeout(10000), // same value, overrides DSN if present
	)

	db := sql.OpenDB(connector) // regular *sql.DB
	defer db.Close()
	// … use db as usual
}

```

The connector stores the DSN and any `ConnectorOption`s, overriding busy-timeout values in the parsed config before opening the native connection (see [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) lines 77-91).

## Core Source Files Reference

Understanding the implementation helps debug complex scenarios:

- **[`bindings/go/driver_db.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/driver_db.go)**: Core `database/sql` driver implementation, DSN parsing, connection and statement handling (lines 70-200)
- **[`bindings/go/driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/driver_sync.go)**: High-level synced-database wrapper (`TursoSyncDb`), `tursoSyncConnector` implementation, push/pull/checkpoint logic, and IO processing (lines 14-132)
- **[`bindings/go/bindings.go`](https://github.com/tursodatabase/turso/blob/main/bindings/go/bindings.go)**: One-time loading of the platform-specific native library via `InitLibrary` (lines 10-21)
- **[`examples/go/sync/sync.go`](https://github.com/tursodatabase/turso/blob/main/examples/go/sync/sync.go)**: Working reference implementation demonstrating sync operations

## Summary

- **Import once**: Use `_ "turso.tech/database/tursogo"` to register the `"turso"` driver name with `database/sql`
- **Local mode**: Call `sql.Open("turso", "file.db?_busy_timeout=5000")` for standalone databases; the `Open` function in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) handles native library initialization and connection setup
- **Sync mode**: Use `turso.NewTursoSyncDb()` for edge-computing scenarios requiring cloud synchronization; it manages push/pull operations and checkpointing via [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go)
- **Standard interface**: Both modes return `*sql.DB` compatible with standard `database/sql` patterns, including connection pooling, prepared statements, and transaction handling
- **IO interleaving**: Synced connections use the `extraIo` hook (`processOneIo`) to perform network operations without blocking SQL execution

## Frequently Asked Questions

### What is the difference between using `sql.Open` and `NewTursoSyncDb`?

`sql.Open("turso", dsn)` creates a standard connection to a local SQLite database file managed by Turso's engine, suitable for single-node applications. `NewTursoSyncDb` creates a high-level wrapper (`TursoSyncDb`) that manages bidirectional synchronization between a local database file and Turso Cloud, handling replication via `Push`, `Pull`, and `Checkpoint` methods defined in [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go).

### How does the driver handle network IO during SQL execution?

The synced driver implements an `extraIo` callback mechanism set in `tursoSyncConnector.Connect` (lines 99-106 in [`driver_sync.go`](https://github.com/tursodatabase/turso/blob/main/driver_sync.go)). During statement stepping, the driver yields control to `processOneIo`, which processes network operations (push/pull) without blocking the main SQL execution thread, enabling asynchronous replication while maintaining query responsiveness.

### Can I use standard `database/sql` features like connection pooling?

Yes. The tursogo driver implements the complete `database/sql` driver interface including `driver.Conn`, `driver.Stmt`, and `driver.Tx`. Connections returned via `sql.Open` or `tursoSyncDb.Connect` support standard connection pooling, prepared statements via `PrepareContext` (lines 131-200 in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go)), and full transaction support via `BeginTx`.

### How do I configure the busy timeout for concurrent access?

Set the `_busy_timeout` parameter in the DSN (e.g., `"my.db?_busy_timeout=5000"`), which is parsed by `parseDSN` in [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go) lines 219-255. Alternatively, use the `WithBusyTimeout()` option when creating a custom connector via `NewConnector`, which overrides the DSN value as implemented in lines 77-91 of [`driver_db.go`](https://github.com/tursodatabase/turso/blob/main/driver_db.go).