# How Turso Language Bindings for Go, JavaScript, Python, Java, and .NET Operate

> Discover how Turso language bindings for Go, JavaScript, Python, Java, and .NET operate. Learn how these FFI wrappers leverage a unified Rust driver for efficient database access.

- Repository: [Turso Database/turso](https://github.com/tursodatabase/turso)
- Tags: internals
- Published: 2026-06-23

---

**Turso's language bindings are thin FFI wrappers around a unified Rust sync driver that exposes C-compatible functions, enabling each host language to call the same libSQL protocol implementation while maintaining idiomatic APIs.**

The `tursodatabase/turso` repository provides official client libraries that allow developers to interact with distributed SQLite databases using familiar syntax in their preferred language. Rather than implementing separate network clients for each ecosystem, Turso leverages a **shared Rust core** compiled to native libraries, which the various language bindings invoke through Foreign Function Interface (FFI) mechanisms. This architecture ensures consistent behavior across Go, JavaScript, Python, Java, and .NET while respecting each platform's performance characteristics and concurrency models.

## The Shared Rust Foundation

### Core Driver Implementation

All language bindings depend on the Rust crate defined in [`bindings/rust/src/lib.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/lib.rs), which exports a C-compatible ABI via `extern "C"` functions. This crate implements connection pooling, statement preparation, and transaction management. The file [`bindings/rust/src/sync.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/sync.rs) contains the **sync driver** logic that communicates with Turso's cloud service over HTTP/2, handling SQLite page updates and replication.

### Build and Linking Strategy

The Rust core compiles into a static library (`.a`) or shared object (`.so`/`.dll`) depending on the target language's requirements. The workspace [`Cargo.toml`](https://github.com/tursodatabase/turso/blob/main/Cargo.toml) governs versioning across all bindings, ensuring that updating the Rust driver automatically propagates to every language wrapper.

## How Each Language Binding Operates

### Go Bindings via CGO

The Go binding resides in `bindings/go/` and utilizes **CGO** to link against the compiled Rust static library. The `go.mod` file defines the module path, while `bindings/go/go-driver-sync.mdx` documents the synchronous API. Go methods map directly to C symbols exported by [`bindings/rust/src/lib.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/lib.rs), wrapped in idiomatic Go types such as `*DB` and `*Stmt`.

### JavaScript Bindings (Node and WebAssembly)

JavaScript support spans two runtimes. For Node.js, the binding in [`bindings/javascript/sync/src/lib.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/javascript/sync/src/lib.rs) compiles to a native addon using **N-API** (via napi-rs), located in `bindings/javascript/sync/packages/native`. For browsers, **wasm-pack** compiles the Rust core to WebAssembly. Both approaches load the compiled module and expose JavaScript-friendly promises, though the underlying Rust driver remains strictly synchronous, with async operations handled in worker threads.

### Python Bindings via PyO3

The Python extension uses **PyO3** and **maturin** (or setuptools-rust) to build the Rust crate as a native Python module. Configuration in [`bindings/python/pyproject.toml`](https://github.com/tursodatabase/turso/blob/main/bindings/python/pyproject.toml) defines the build pipeline. Functions like `turso.connect` directly invoke the Rust connection logic from [`bindings/rust/src/lib.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/lib.rs), returning Python objects that wrap the underlying database handles.

### Java Bindings via JNI

Java integration uses the **Java Native Interface (JNI)**. The build process generates JNI headers from the C symbols in the Rust core, with Java classes loading the native library via `System.loadLibrary("turso")`. Documentation in `bindings/java/java-driver-sync.mdx` outlines how the JVM delegates calls to [`bindings/rust/src/connection.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/connection.rs) and [`bindings/rust/src/transaction.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/transaction.rs).

### .NET Bindings via P/Invoke

The .NET wrapper employs **P/Invoke** through `DllImport` attributes to call the C-ABI exported by the Rust DLL. The C# implementation provides managed wrappers like `TursoConnection` and `TursoCommand` that marshal data between .NET types and the native Rust structures, as described in `bindings/dotnet/dotnet-driver-sync.mdx`.

## Working Code Examples

### Connecting from Go

```go
package main

import (
	"log"

	"github.com/tursodatabase/turso/bindings/go"
)

func main() {
	// Open a connection to a Turso database (replace <URL> with your libSQL URL)
	db, err := go.Open("libsql://<TOKEN>@<HOST>/<DB>")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Execute a simple query
	row, err := db.QueryRow("SELECT sqlite_version()")
	if err != nil {
		log.Fatal(err)
	}
	var version string
	if err := row.Scan(&version); err != nil {
		log.Fatal(err)
	}
	log.Println("SQLite version:", version)
}

```

### Querying from JavaScript (Node.js)

```javascript
import { Database } from "turso-sync";

const db = new Database("libsql://<TOKEN>@<HOST>/<DB>");

(async () => {
  const rows = await db.execute("SELECT name FROM sqlite_master WHERE type='table'");
  console.log(rows);
})();

```

### Executing SQL in Python

```python
import turso

# Create a connection (URL includes auth token)

conn = turso.connect("libsql://<TOKEN>@<HOST>/<DB>")
cur = conn.cursor()
cur.execute("SELECT sqlite_version()")
print("SQLite version:", cur.fetchone()[0])
conn.close()

```

### Java and .NET Examples

**Java:**

```java
import com.turso.Database;

public class Main {
    public static void main(String[] args) throws Exception {
        Database db = new Database("libsql://<TOKEN>@<HOST>/<DB>");
        try (var stmt = db.prepareStatement("SELECT sqlite_version()")) {
            var rs = stmt.executeQuery();
            if (rs.next()) {
                System.out.println("SQLite version: " + rs.getString(1));
            }
        }
        db.close();
    }
}

```

**C# (.NET):**

```csharp
using Turso;

var db = new TursoConnection("libsql://<TOKEN>@<HOST>/<DB>");
db.Open();

using var cmd = db.CreateCommand();
cmd.CommandText = "SELECT sqlite_version()";
var version = cmd.ExecuteScalar()!.ToString();
Console.WriteLine($"SQLite version: {version}");

db.Close();

```

## Summary

- All Turso language bindings rely on a **single Rust core** located in [`bindings/rust/src/lib.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/lib.rs) that exposes a C-compatible ABI for universal interoperability.
- **FFI mechanisms** vary by language: Go uses CGO, Python uses PyO3, Java uses JNI, .NET uses P/Invoke, and JavaScript uses N-API or WebAssembly.
- The Rust driver implements a **synchronous, blocking** API for libSQL protocol communication; languages requiring async semantics (like JavaScript) handle concurrency through worker threads or promise wrappers.
- Shared versioning via the workspace [`Cargo.toml`](https://github.com/tursodatabase/turso/blob/main/Cargo.toml) ensures consistent feature parity and bug fixes across Go, JavaScript, Python, Java, and .NET simultaneously.

## Frequently Asked Questions

### Do the Turso language bindings support async/await patterns?

While the underlying Rust driver in [`bindings/rust/src/sync.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/sync.rs) operates synchronously, language bindings that target async ecosystems implement wrappers to accommodate non-blocking workflows. JavaScript bindings, for example, run the driver in worker threads and expose Promise-based APIs, whereas Python and Go bindings typically expose synchronous interfaces that can be wrapped in language-specific async constructs.

### Why does Turso use Rust for the driver core instead of native implementations?

Turso uses a **unified Rust core** to eliminate code duplication and ensure protocol consistency across all supported languages. By compiling to a C-compatible library once and exposing it via FFI, the project maintains a single source of truth for connection management, replication logic, and SQL parsing, reducing the maintenance burden across `bindings/go/`, `bindings/python/`, and other directories.

### How are transactions handled across the different language bindings?

Transactions are managed through the Rust core's transaction API defined in [`bindings/rust/src/transaction.rs`](https://github.com/tursodatabase/turso/blob/main/bindings/rust/src/transaction.rs), which all bindings invoke via their respective FFI layers. Whether using Go's `*Tx` type, Python's connection context managers, or Java's `Transaction` objects, each binding ultimately calls the same native functions to begin, commit, or rollback transactions on the remote Turso database.

### Can I use the Turso language bindings with self-hosted libSQL instances?

Yes, because the Rust driver implements the **libSQL wire protocol**, the language bindings can connect to any compatible endpoint, including self-hosted libSQL servers or local SQLite files, by specifying the appropriate connection string in `go.Open`, `turso.connect`, or the equivalent constructor in Java and .NET.