# Turso

## Docs

- [List Audit Logs](https://docs.turso.tech/api-reference/audit-logs/list): Return the audit logs for the given organization, ordered by the `created_at` field in descending order.
- [Authentication](https://docs.turso.tech/api-reference/authentication)
- [Retrieve Database Configuration](https://docs.turso.tech/api-reference/databases/configuration): Retrieve an individual database configuration belonging to the organization or user.
- [Create Database](https://docs.turso.tech/api-reference/databases/create): Creates a new database in a group for the organization or user.
- [Generate Database Auth Token](https://docs.turso.tech/api-reference/databases/create-token): Generates an authorization token for the specified database.
- [Delete Database](https://docs.turso.tech/api-reference/databases/delete): Delete a database belonging to the organization or user.
- [Invalidate All Database Auth Tokens](https://docs.turso.tech/api-reference/databases/invalidate-tokens): Invalidates all authorization tokens for the specified database.
- [List Databases](https://docs.turso.tech/api-reference/databases/list): Returns a list of databases belonging to the organization or user.
- [List Database Instances](https://docs.turso.tech/api-reference/databases/list-instances): Returns a list of instances of a database. Instances are the individual primary or replica databases in each region defined by the group.
- [Retrieve Database](https://docs.turso.tech/api-reference/databases/retrieve): Returns a database belonging to the organization or user.
- [Retrieve Database Instance](https://docs.turso.tech/api-reference/databases/retrieve-instance): Return the individual database instance by name.
- [Retrieve Database Stats](https://docs.turso.tech/api-reference/databases/stats): Fetch the top queries of a database, including the count of rows read and written.
- [Update Database Configuration](https://docs.turso.tech/api-reference/databases/update-configuration): Update a database configuration belonging to the organization or user.
- [Upload SQLite Dump](https://docs.turso.tech/api-reference/databases/upload-dump): Upload a SQL dump to be used when [creating a new database](/api-reference/databases/create) from seed.
- [Retrieve Database Usage](https://docs.turso.tech/api-reference/databases/usage): Fetch activity usage for a database in a given time period.
- [Add Location to Group](https://docs.turso.tech/api-reference/groups/add-location): Adds a location to the specified group.
- [Create Group](https://docs.turso.tech/api-reference/groups/create): Creates a new group for the organization or user.
- [Create Group Auth Token](https://docs.turso.tech/api-reference/groups/create-token): Generates an authorization token for the specified group.
- [Delete Group](https://docs.turso.tech/api-reference/groups/delete): Delete a group belonging to the organization or user.
- [Invalidate All Group Auth Tokens](https://docs.turso.tech/api-reference/groups/invalidate-tokens): Invalidates all authorization tokens for the specified group.
- [List Groups](https://docs.turso.tech/api-reference/groups/list): Returns a list of groups belonging to the organization or user.
- [Remove Location from Group](https://docs.turso.tech/api-reference/groups/remove-location): Removes a location from the specified group.
- [Retrieve Group](https://docs.turso.tech/api-reference/groups/retrieve): Returns a group belonging to the organization or user.
- [Transfer Group](https://docs.turso.tech/api-reference/groups/transfer): Transfer a group to another organization that you own or a member of.
- [Unarchive Group](https://docs.turso.tech/api-reference/groups/unarchive): Unarchive a group that has been archived due to inactivity.
- [Update Databases in a Group](https://docs.turso.tech/api-reference/groups/update-database-versions): Updates all databases in the group to the latest libSQL version.
- [Turso Platform API](https://docs.turso.tech/api-reference/introduction)
- [Closest Region](https://docs.turso.tech/api-reference/locations/closest-region): Returns the closest region to the user's location.
- [List Locations](https://docs.turso.tech/api-reference/locations/list): Returns a list of locations where you can create or replicate databases.
- [Create Invite](https://docs.turso.tech/api-reference/organizations/invites/create): Invite a user (who isn't already a Turso user) to an organization.
- [Delete Invite](https://docs.turso.tech/api-reference/organizations/invites/delete): Delete an invite for the organization by email.
- [List Invites](https://docs.turso.tech/api-reference/organizations/invites/list): Returns a list of invites for the organization.
- [List Invoices](https://docs.turso.tech/api-reference/organizations/invoices): Returns a list of invoices for the organization.
- [List Organizations](https://docs.turso.tech/api-reference/organizations/list): Returns a list of organizations the authenticated user owns or is a member of.
- [Add Member](https://docs.turso.tech/api-reference/organizations/members/add): Add an existing Turso user to an organization.
- [List Members](https://docs.turso.tech/api-reference/organizations/members/list): Returns a list of members part of the organization.
- [Remove Member](https://docs.turso.tech/api-reference/organizations/members/remove): Remove a user from the organization by username.
- [List Plans](https://docs.turso.tech/api-reference/organizations/plans): Returns a list of available plans and their quotas.
- [Current Subscription](https://docs.turso.tech/api-reference/organizations/subscription): Returns the current subscription details for the organization.
- [Update Organization](https://docs.turso.tech/api-reference/organizations/update): Update an organization you own or are a member of.
- [Organization Usage](https://docs.turso.tech/api-reference/organizations/usage): Fetch current billing cycle usage for an organization.
- [Quickstart](https://docs.turso.tech/api-reference/quickstart): Get started with Turso API in a few easy steps.
- [Errors](https://docs.turso.tech/api-reference/response-codes)
- [Create API Token](https://docs.turso.tech/api-reference/tokens/create): Returns a new API token belonging to a user.
- [List API Tokens](https://docs.turso.tech/api-reference/tokens/list): Returns a list of API tokens belonging to a user.
- [Revoke API Token](https://docs.turso.tech/api-reference/tokens/revoke): Revokes the provided API token belonging to a user.
- [Validate API Token](https://docs.turso.tech/api-reference/tokens/validate): Validates an API token belonging to a user.
- [auth api-tokens list](https://docs.turso.tech/cli/auth/api-tokens/list)
- [auth api-tokens mint](https://docs.turso.tech/cli/auth/api-tokens/mint)
- [auth api-tokens revoke](https://docs.turso.tech/cli/auth/api-tokens/revoke)
- [auth login](https://docs.turso.tech/cli/auth/login)
- [auth logout](https://docs.turso.tech/cli/auth/logout)
- [auth signup](https://docs.turso.tech/cli/auth/signup)
- [auth token](https://docs.turso.tech/cli/auth/token)
- [auth whoami](https://docs.turso.tech/cli/auth/whoami)
- [Authentication](https://docs.turso.tech/cli/authentication)
- [contact bookmeeting](https://docs.turso.tech/cli/contact/bookmeeting)
- [contact feedback](https://docs.turso.tech/cli/contact/feedback)
- [db config attach allow](https://docs.turso.tech/cli/db/config/attach/allow)
- [db config attach disallow](https://docs.turso.tech/cli/db/config/attach/disallow)
- [db config attach show](https://docs.turso.tech/cli/db/config/attach/show)
- [db create](https://docs.turso.tech/cli/db/create)
- [db destroy](https://docs.turso.tech/cli/db/destroy)
- [db inspect](https://docs.turso.tech/cli/db/inspect)
- [db list](https://docs.turso.tech/cli/db/list)
- [db locations](https://docs.turso.tech/cli/db/locations)
- [db shell](https://docs.turso.tech/cli/db/shell)
- [db show](https://docs.turso.tech/cli/db/show)
- [db tokens create](https://docs.turso.tech/cli/db/tokens/create)
- [db tokens invalidate](https://docs.turso.tech/cli/db/tokens/invalidate)
- [dev](https://docs.turso.tech/cli/dev)
- [group create](https://docs.turso.tech/cli/group/create)
- [group destroy](https://docs.turso.tech/cli/group/destroy)
- [group list](https://docs.turso.tech/cli/group/list)
- [group locations add](https://docs.turso.tech/cli/group/locations/add)
- [group locations list](https://docs.turso.tech/cli/group/locations/list)
- [group locations remove](https://docs.turso.tech/cli/group/locations/remove)
- [group tokens create](https://docs.turso.tech/cli/group/tokens/create)
- [group tokens invalidate](https://docs.turso.tech/cli/group/tokens/invalidate)
- [group transfer](https://docs.turso.tech/cli/group/transfer)
- [group unarchive](https://docs.turso.tech/cli/group/unarchive)
- [group update](https://docs.turso.tech/cli/group/update)
- [Headless Mode](https://docs.turso.tech/cli/headless-mode)
- [Help](https://docs.turso.tech/cli/help)
- [Installation](https://docs.turso.tech/cli/installation): Learn how to install the Turso CLI on Mac, Linux and Windows.
- [Introduction](https://docs.turso.tech/cli/introduction)
- [org billing](https://docs.turso.tech/cli/org/billing)
- [org create](https://docs.turso.tech/cli/org/create)
- [destroy](https://docs.turso.tech/cli/org/destroy)
- [org list](https://docs.turso.tech/cli/org/list)
- [org members add](https://docs.turso.tech/cli/org/members/add)
- [org members invite](https://docs.turso.tech/cli/org/members/invite)
- [org members list](https://docs.turso.tech/cli/org/members/list)
- [org members rm](https://docs.turso.tech/cli/org/members/rm)
- [org switch](https://docs.turso.tech/cli/org/switch)
- [plan overages disable](https://docs.turso.tech/cli/plan/overages/disable)
- [plan overages enable](https://docs.turso.tech/cli/plan/overages/enable)
- [plan select](https://docs.turso.tech/cli/plan/select)
- [plan show](https://docs.turso.tech/cli/plan/show)
- [plan upgrade](https://docs.turso.tech/cli/plan/upgrade)
- [Upgrading](https://docs.turso.tech/cli/upgrading): Update the Turso CLI to the latest version to benefit from all the latest features, and fixes.
- [Turso Concepts](https://docs.turso.tech/concepts)
- [Data & Connections](https://docs.turso.tech/data-and-connections): Learn how data consistency and connections work with Turso databases.
- [AI & Embeddings](https://docs.turso.tech/features/ai-and-embeddings): Vector Similarity Search is built into Turso and libSQL Server as a native feature.
- [Attach Database](https://docs.turso.tech/features/attach-database): Attach and read data across multiple databases.
- [Branching](https://docs.turso.tech/features/branching)
- [Data Edge](https://docs.turso.tech/features/data-edge): Allow your users to reach local replicas of your database, wherever they are.
- [Embedded Replicas](https://docs.turso.tech/features/embedded-replicas/introduction)
- [Turso + Linode by Akamai](https://docs.turso.tech/features/embedded-replicas/with-akamai): Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Akamai](https://www.linode.com/).
- [Embedded Replicas on Fly](https://docs.turso.tech/features/embedded-replicas/with-fly): Deploy a JavaScript app using [Turso embedded replicas](/features/embedded-replicas) to [Fly.io](https://www.fly.io/).
- [Turso + Koyeb](https://docs.turso.tech/features/embedded-replicas/with-koyeb): Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Koyeb](https://www.koyeb.com/).
- [Turso + Railway](https://docs.turso.tech/features/embedded-replicas/with-railway): Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Railway](https://railway.app/).
- [Turso + Render](https://docs.turso.tech/features/embedded-replicas/with-render): Deploy a JavaScript app using [Turso embedded replicas](/features/embedded-replicas) to [Render](https://render.com/).
- [Multi-DB Schemas](https://docs.turso.tech/features/multi-db-schemas): Create and share a single schema across multiple databases.
- [Platform API](https://docs.turso.tech/features/platform-api): Manage databases, replicas, and teams with the Turso Platform API.
- [Point-in-Time Recovery](https://docs.turso.tech/features/point-in-time-recovery)
- [Scale to Zero](https://docs.turso.tech/features/scale-to-zero)
- [Usage & Billing](https://docs.turso.tech/help/usage-and-billing)
- [Welcome to Turso](https://docs.turso.tech/introduction): SQLite for Production. Powered by libSQL.
- [libSQL](https://docs.turso.tech/libsql): libSQL is SQLite for modern applications.
- [Local Development](https://docs.turso.tech/local-development): Build locally using SQLite, libSQL Server or Turso.
- [Quickstart](https://docs.turso.tech/quickstart): Welcome to Turso! Get started with Turso in minutes.
- [Authentication](https://docs.turso.tech/sdk/authentication)
- [Turso Examples (C)](https://docs.turso.tech/sdk/c/examples)
- [Turso Quickstart (C)](https://docs.turso.tech/sdk/c/quickstart): Get started with Turso and C using the libSQL client in a few simple steps.
- [C Reference](https://docs.turso.tech/sdk/c/reference): libSQL C Reference
- [Examples](https://docs.turso.tech/sdk/flutter/examples)
- [Drift + Turso / LibSQL](https://docs.turso.tech/sdk/flutter/integrations/drift): Configure `drift` to work with `libsql_dart`
- [Turso Quickstart (Flutter / Dart)](https://docs.turso.tech/sdk/flutter/quickstart): Get started with Flutter and Dart using the libSQL client in a few simple steps
- [Reference](https://docs.turso.tech/sdk/flutter/reference): libSQL Flutter / Dart Reference
- [Examples](https://docs.turso.tech/sdk/go/examples)
- [Turso Quickstart (Go)](https://docs.turso.tech/sdk/go/quickstart): Get started with Turso and Go using the libSQL client in a few simple steps.
- [Reference](https://docs.turso.tech/sdk/go/reference)
- [Turso Quickstart (HTTP)](https://docs.turso.tech/sdk/http/quickstart): Get started with Turso using the libSQL remote protocol in a few simple steps.
- [libSQL Remote Protocol Reference](https://docs.turso.tech/sdk/http/reference)
- [Introduction](https://docs.turso.tech/sdk/introduction)
- [Turso Quickstart (Android)](https://docs.turso.tech/sdk/kotlin/quickstart): Get started with Turso and Android using the libSQL client in a few simple steps.
- [Android Reference](https://docs.turso.tech/sdk/kotlin/reference): libSQL Android Reference
- [Examples](https://docs.turso.tech/sdk/php/examples)
- [Turso + Laravel](https://docs.turso.tech/sdk/php/guides/laravel): Set up Turso in your Laravel project in minutes
- [Turso + Doctrine DBAL](https://docs.turso.tech/sdk/php/orm/doctrine-dbal): Set up Turso in your PHP + Doctrine DBAL project in minutes
- [Turso Quickstart (PHP)](https://docs.turso.tech/sdk/php/quickstart): Get started with Turso and PHP using the libSQL client in a few simple steps.
- [Reference](https://docs.turso.tech/sdk/php/reference): libSQL PHP Reference
- [Examples](https://docs.turso.tech/sdk/python/examples)
- [Flask + Turso](https://docs.turso.tech/sdk/python/guides/flask): Set up Turso in your Flask project in minutes
- [SQLAlchemy + Turso](https://docs.turso.tech/sdk/python/orm/sqlalchemy): Configure SQLAlchemy to work with your Turso database
- [Turso Quickstart (Python)](https://docs.turso.tech/sdk/python/quickstart): Get started with Turso and Python using the libSQL client in a few simple steps.
- [Reference](https://docs.turso.tech/sdk/python/reference)
- [Turso Examples (Ruby)](https://docs.turso.tech/sdk/ruby/examples)
- [Turso Quickstart (Ruby)](https://docs.turso.tech/sdk/ruby/quickstart): Get started with Turso and Ruby using the libSQL client in a few simple steps.
- [Examples](https://docs.turso.tech/sdk/rust/examples)
- [Turso + Actix](https://docs.turso.tech/sdk/rust/guides/actix): Set up Turso in your Actix project in minutes
- [Turso + Axum](https://docs.turso.tech/sdk/rust/guides/axum): Set up Turso in your Axum project in minutes
- [Turso + Rocket](https://docs.turso.tech/sdk/rust/guides/rocket): Set up Turso in your Rocket project in minutes
- [Tauri + Turso](https://docs.turso.tech/sdk/rust/guides/tauri): Set up Turso in your Tauri project in minutes
- [Turso Quickstart (Rust)](https://docs.turso.tech/sdk/rust/quickstart): Get started with Turso and Rust using the libSQL crate in a few simple steps
- [Reference](https://docs.turso.tech/sdk/rust/reference): libSQL Rust Reference
- [Turso Quickstart (Swift)](https://docs.turso.tech/sdk/swift/quickstart): Get started with Turso and Swift using the libSQL client in a few simple steps.
- [Swift Reference](https://docs.turso.tech/sdk/swift/reference): libSQL Swift Reference
- [Examples](https://docs.turso.tech/sdk/ts/examples)
- [Astro + Turso](https://docs.turso.tech/sdk/ts/guides/astro): Set up Turso in your Astro project in minutes.
- [Elysia + Turso](https://docs.turso.tech/sdk/ts/guides/elysia): Set up Turso in your Elysia project in minutes.
- [Hono + Turso](https://docs.turso.tech/sdk/ts/guides/hono): Set up Turso in your Hono project in minutes.
- [Next.js + Turso](https://docs.turso.tech/sdk/ts/guides/nextjs): Set up Turso in your Next.js project in minutes.
- [Nuxt + Turso](https://docs.turso.tech/sdk/ts/guides/nuxt): Set up Turso in your Nuxt project in minutes
- [Quasar + Turso](https://docs.turso.tech/sdk/ts/guides/quasar): Set up Turso in your Quasar project in minutes
- [Qwik + Turso](https://docs.turso.tech/sdk/ts/guides/qwik): Set up Turso in your Qwik project in minutes
- [Remix + Turso](https://docs.turso.tech/sdk/ts/guides/remix): Set up Turso in your Remix project in minutes
- [SvelteKit + Turso](https://docs.turso.tech/sdk/ts/guides/sveltekit): Set up Turso in your SvelteKit project in minutes
- [Sentry](https://docs.turso.tech/sdk/ts/integrations/sentry): Trace slow queries and capture SQL errors with Sentry.
- [Drizzle + Turso](https://docs.turso.tech/sdk/ts/orm/drizzle): Configure Drizzle to work with Turso
- [Prisma + Turso](https://docs.turso.tech/sdk/ts/orm/prisma): Configure Prisma to work with your Turso database
- [Turso Quickstart (TypeScript / JS)](https://docs.turso.tech/sdk/ts/quickstart): Get started with Turso and TypeScript using the libSQL client in a few simple steps
- [Reference](https://docs.turso.tech/sdk/ts/reference): libSQL JavaScript and TypeScript Reference
- [Support](https://docs.turso.tech/support): We're always here to help.


## Optional

- [Turso Homepage](https://turso.tech)
- [Blog & Tutorials](https://turso.tech/blog)
- [Discord](https://discord.gg/turso)
- [GitHub](https://github.com/tursodatabase)


# List Audit Logs

GET /v1/organizations/{organizationName}/audit-logs
Return the audit logs for the given organization, ordered by the `created_at` field in descending order.

<Warning>Audit Logs are limited to paid plans.</Warning>

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/audit-logs \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Authentication



The Turso API uses API tokens to authenticate requests. You can create and revoke API tokens using the [Turso CLI](/cli) and [Authentication API](/api-reference/tokens/create).

API tokens allow access to manage all API resources, including creating and destroying database.

*   Use environment variables when working with API tokens.
*   Never share your API token in public, including repositories, and CI/CD Actions.

Turso uses Bearer authentication, and requires your API token to be passed with all protected requests in the `Authorization` header:

```bash
Authorization: Bearer TOKEN
```

## Base URL

The Turso API is located at the following URL:

```bash
https://api.turso.tech
```


# Retrieve Database Configuration

GET /v1/organizations/{organizationName}/databases/{databaseName}/configuration
Retrieve an individual database configuration belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L -X GET 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/configuration' \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Create Database

POST /v1/organizations/{organizationName}/databases
Creates a new database in a group for the organization or user.

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "name": "new-database",
        "group": "default"
    }'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const database = await turso.databases.create("new-database", {
    group: "default",
  });
  ```
</RequestExample>


# Generate Database Auth Token

POST /v1/organizations/{organizationName}/databases/{databaseName}/auth/tokens
Generates an authorization token for the specified database.

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/auth/tokens?expiration=2w&authorization=full-access' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const token = await turso.databases.createToken("my-db", {
    expiration: "2w",
    authorization: "full-access",
  });
  ```
</RequestExample>

<ResponseExample>
  ```json
  {
    "jwt": "TOKEN"
  }
  ```
</ResponseExample>


# Delete Database

DELETE /v1/organizations/{organizationName}/databases/{databaseName}
Delete a database belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const database = await turso.databases.delete("my-db");
  ```
</RequestExample>


# Invalidate All Database Auth Tokens

POST /v1/organizations/{organizationName}/databases/{databaseName}/auth/rotate
Invalidates all authorization tokens for the specified database.

<Warning>
  A short downtime is required to complete the changes.
</Warning>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/auth/rotate' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const response = await turso.databases.rotateTokens("my-db");
  ```
</RequestExample>


# List Databases

GET /v1/organizations/{organizationName}/databases
Returns a list of databases belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/databases \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const databases = await turso.databases.list();
  ```
</RequestExample>


# List Database Instances

GET /v1/organizations/{organizationName}/databases/{databaseName}/instances
Returns a list of instances of a database. Instances are the individual primary or replica databases in each region defined by the group.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/instances \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const instances = await turso.databases.listInstances("my-db");
  ```
</RequestExample>


# Retrieve Database

GET /v1/organizations/{organizationName}/databases/{databaseName}
Returns a database belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const database = await turso.databases.retrieve("my-db");
  ```
</RequestExample>


# Retrieve Database Instance

GET /v1/organizations/{organizationName}/databases/{databaseName}/instances/{instanceName}
Return the individual database instance by name.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/instances/{instanceName} \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const instance = await turso.databases.retrieveInstance("my-db", "lhr");
  ```
</RequestExample>


# Retrieve Database Stats

GET /v1/organizations/{organizationName}/databases/{databaseName}/stats
Fetch the top queries of a database, including the count of rows read and written.

<RequestExample>
  ```bash cURL
  curl -L -X GET 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/stats' \
  -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Update Database Configuration

PATCH /v1/organizations/{organizationName}/databases/{databaseName}/configuration
Update a database configuration belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L -X PATCH 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/configuration' \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "size_limit": "500mb",
        "allow_attach": true
    }'
  ```
</RequestExample>


# Upload SQLite Dump

POST /v1/organizations/{organizationName}/databases/dumps
Upload a SQL dump to be used when [creating a new database](/api-reference/databases/create) from seed.

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases/dumps' \
    -H 'Authorization: Bearer TOKEN' \
    -F 'file=@"~/Downloads/dump.sql"'
  ```
</RequestExample>


# Retrieve Database Usage

GET /v1/organizations/{organizationName}/databases/{databaseName}/usage
Fetch activity usage for a database in a given time period.

<RequestExample>
  ```bash cURL
  curl -L -X GET 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/usage?from=2023-01-01T00:00:00Z&to=2023-02-01T00:00:00Z' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const usageStatsWithDate = await turso.databases.usage("my-db");

  const usageStatsWithDate = await turso.databases.usage("my-db", {
    from: new Date("2023-01-01"),
    to: new Date("2023-02-01"),
  });

  const usageStatsWithString = await turso.databases.usage("my-db", {
    from: "2023-01-01T00:00:00Z",
    to: "2023-02-01T00:00:00Z",
  });
  ```
</RequestExample>


# Add Location to Group

POST /v1/organizations/{organizationName}/groups/{groupName}/locations/{location}
Adds a location to the specified group.

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const group = await turso.groups.addLocation("default", "ams");
  ```
</RequestExample>


# Create Group

POST /v1/organizations/{organizationName}/groups
Creates a new group for the organization or user.

<Warning>
  Creating more than one group is limited to Scaler, Pro and Enterprise plans.
</Warning>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups' \
  -H 'Authorization: Bearer TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
      "name": "new-group",
      "location": "lhr"
  }'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const group = await turso.groups.create("new-group", {
    location: "lhr",
    extensions: ["vector", "uuid"], // 'all'
  });
  ```
</RequestExample>


# Create Group Auth Token

POST /v1/organizations/{organizationName}/groups/{groupName}/auth/tokens
Generates an authorization token for the specified group.

<Info>
  Tokens cannot be retrieved once created, and cannot be revoked individually.
</Info>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/auth/tokens?expiration=2w&authorization=full-access' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const token = await turso.groups.createToken("default", {
    expiration: "2w",
    authorization: "full-access",
  });
  ```
</RequestExample>

<ResponseExample>
  ```json
  {
    "jwt": "TOKEN"
  }
  ```
</ResponseExample>


# Delete Group

DELETE /v1/organizations/{organizationName}/groups/{groupName}
Delete a group belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const group = await turso.groups.delete("new-group");
  ```
</RequestExample>


# Invalidate All Group Auth Tokens

POST /v1/organizations/{organizationName}/groups/{groupName}/auth/rotate
Invalidates all authorization tokens for the specified group.

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/auth/rotate' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const response = await turso.groups.invalidateTokens("default");
  ```
</RequestExample>


# List Groups

GET /v1/organizations/{organizationName}/groups
Returns a list of groups belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/groups \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const groups = await turso.groups.list();
  ```
</RequestExample>


# Remove Location from Group

DELETE /v1/organizations/{organizationName}/groups/{groupName}/locations/{location}
Removes a location from the specified group.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const group = await turso.groups.removeLocation("default", "ams");
  ```
</RequestExample>


# Retrieve Group

GET /v1/organizations/{organizationName}/groups/{groupName}
Returns a group belonging to the organization or user.

<RequestExample>
  ```bash cURL
  curl -L 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const group = await turso.groups.retrieve("default");
  ```
</RequestExample>


# Transfer Group

POST /v1/organizations/{organizationName}/groups/{groupName}/transfer
Transfer a group to another organization that you own or a member of.

<Info>
  You can only transfer groups to organizations you own or are an admin.
</Info>

<Warning>
  Existing database URL and tokens will continue to work, but should update your application to use the new URL and token as soon as possible.
</Warning>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/transfer' \
  -H 'Authorization: Bearer TOKEN' \
  -d '{
      "organization": "new-organization-name"
  }'
  ```
</RequestExample>


# Unarchive Group

POST /v1/organizations/{organizationName}/groups/{groupName}/unarchive
Unarchive a group that has been archived due to inactivity.

<Info>
  Databases get archived after 10 days of inactivity for users on a free plan — [learn more](/features/scale-to-zero). You can unarchive inactive groups using the API.
</Info>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/unarchive' \
  -H 'Authorization: Bearer TOKEN' \
  ```
</RequestExample>


# Update Databases in a Group

POST /v1/organizations/{organizationName}/groups/{groupName}/update
Updates all databases in the group to the latest libSQL version.

<Warning>
  This operation causes some amount of downtime to occur during the update process. The version of libSQL server is taken from the latest built docker image.
</Warning>

<RequestExample>
  ```bash cURL
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/update' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const database = await turso.groups.update("default");
  ```
</RequestExample>


# Turso Platform API



The Turso API gives you everything needed to manage your organization and its members, groups, databases, and API tokens.

If you want to programatically create and manage databases, either for building a platform where you provide SQLite databases to your users or have a per-user SQLite database architecture, this is the API to do that.

<CardGroup cols={2}>
  <Card title="API Quickstart" icon="play" href="/api-reference/quickstart">
    Get started with the Turso API to create your first database.
  </Card>
</CardGroup>

## API Resources

Start integrating the Turso API with your platform in a few simple steps.

<Snippet file="platform-api-links.mdx" />


# Closest Region

GET https://region.turso.io
Returns the closest region to the user's location.

#### Response

<ResponseField name="server" type="string">
  The location code for the server responding.
</ResponseField>

<ResponseField name="client" type="string">
  The location code for the client request.
</ResponseField>

<RequestExample>
  ```bash cURL
  curl https://region.turso.io
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const { server, client } = await turso.locations.closest();
  ```
</RequestExample>

<ResponseExample>
  ```json 200
  {
    "server": "lhr",
    "client": "lhr"
  }
  ```
</ResponseExample>


# List Locations

GET /v1/locations
Returns a list of locations where you can create or replicate databases.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/locations \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const locations = await turso.locations.list();
  ```
</RequestExample>


# Create Invite

POST /v1/organizations/{organizationName}/invites
Invite a user (who isn't already a Turso user) to an organization.

<Info>
  If you want to invite someone who is already a registered Turso user, you can [add them](/api-reference/organizations/members/add) instead.
</Info>

<Info>
  You must be an `owner` or `admin` to invite other users. **You can only invite users to a team and not your personal account.**
</Info>


# Delete Invite

DELETE /v1/organizations/{organizationName}/invites/{email}
Delete an invite for the organization by email.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE https://api.turso.tech/v1/organizations/{organizationName}/invites/{email} \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# List Invites

GET /v1/organizations/{organizationName}/invites
Returns a list of invites for the organization.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/invites \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const invites = await turso.organizations.invites("mycompany");
  ```
</RequestExample>


# List Invoices

GET /v1/organizations/{organizationName}/invoices
Returns a list of invoices for the organization.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/invoices \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# List Organizations

GET /v1/organizations
Returns a list of organizations the authenticated user owns or is a member of.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const organizations = await turso.organizations.list();
  ```
</RequestExample>


# Add Member

POST /v1/organizations/{organizationName}/members
Add an existing Turso user to an organization.

<Info>
  If you want to add someone who is not a registered Turso user, you can [create an invite](/api-reference/organizations/invites/create) instead.
</Info>

<Info>
  You must be an `owner` or `admin` to add other members. **You can only add users to a team and not your personal account.**
</Info>


# List Members

GET /v1/organizations/{organizationName}/members
Returns a list of members part of the organization.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/members \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const members = await turso.organizations.members("mycompany");
  ```
</RequestExample>


# Remove Member

DELETE /v1/organizations/{organizationName}/members/{username}
Remove a user from the organization by username.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE https://api.turso.tech/v1/organizations/{organizationName}/members/{username} \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const member = await turso.organizations.removeMember("mycompany", "iku");
  ```
</RequestExample>


# List Plans

GET /v1/organizations/{organizationName}/plans
Returns a list of available plans and their quotas.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/plans \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Current Subscription

GET /v1/organizations/{organizationName}/subscription
Returns the current subscription details for the organization.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/subscription \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Update Organization

PATCH /v1/organizations/{organizationName}
Update an organization you own or are a member of.

<RequestExample>
  ```bash cURL
  curl -L -X PATCH https://api.turso.tech/v1/organizations/{organizationName} \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "overages": true
    }'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const organization = await turso.organizations.update("mycompany", {
    overages: true,
  });
  ```
</RequestExample>


# Organization Usage

GET /v1/organizations/{organizationName}/usage
Fetch current billing cycle usage for an organization.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/organizations/{organizationName}/usage \
    -H 'Authorization: Bearer TOKEN'
  ```
</RequestExample>


# Quickstart

Get started with Turso API in a few easy steps.

<Steps>
  <Step title="Signup or Login using the Turso CLI">
    Make sure to [install the Turso CLI](/cli/installation) if you haven't
    already.

    <CodeGroup>
      ```bash Signup
      turso auth signup
      ```

      ```bash Login
      turso auth login
      ```
    </CodeGroup>
  </Step>

  <Step title="Retrieve your account or organization slug">
    The Platform API can be used with your personal account or with an organization. You'll need the obtain the `slug` of your account or organization using using the Turso CLI:

    ```bash
    turso org list
    ```
  </Step>

  <Step title="Create a new Platform API Token">
    Now create a new API Token using the Turso CLI:

    ```bash
    turso auth api-tokens mint quickstart
    ```

    <Info>
      Make sure to save the token somewhere safe. We'll need it next.
    </Info>
  </Step>

  <Step title="Fetch available Locations">
    Before we can create a group or database in a specific region, we'll need to fetch the list of available regions:

    <CodeGroup>
      ```bash cURL
      curl -L 'https://api.turso.tech/v1/locations' \
        -H 'Authorization: Bearer TOKEN' \
      ```

      ```ts Node.js
      import { createClient } from "@tursodatabase/api";

      const turso = createClient({
        org: "...",
        token: "",
      });

      const locations = await turso.locations.list();
      ```
    </CodeGroup>

    <br />

    <Info>
      The `organizationName` is the name of your organization or personal account.
    </Info>
  </Step>

  <Step title="Create a Group">
    All databases belong to a group that can exist in one or more locations.

    Begin by creating a group, giving it a `name` and primary `location`:

    <CodeGroup>
      ```bash cURL
      curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups' \
        -H 'Authorization: Bearer TOKEN' \
        -H 'Content-Type: application/json' \
        -d '{
            "name": "default",
            "location": "lhr"
        }'
      ```

      ```ts Node.js
      import { createClient } from "@tursodatabase/api";

      const turso = createClient({
        org: "...",
        token: "",
      });

      const group = await turso.groups.addLocation("default", "lhr");
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a Database">
    Now create your first database in the group you created above:

    <CodeGroup>
      ```bash cURL
      curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
        -H 'Authorization: Bearer TOKEN' \
        -H 'Content-Type: application/json' \
        -d '{
            "name": "my-db",
            "group": "default"
        }'
      ```

      ```ts Node.js
      import { createClient } from "@tursodatabase/api";

      const turso = createClient({
        org: "...",
        token: "",
      });

      const database = await turso.databases.create("my-db", "ams");
      ```
    </CodeGroup>
  </Step>

  <Step title="Replicate Database to another region">
    Add another location to your group to replicate your database to another region:

    <CodeGroup>
      ```bash cURL
      curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
        -H 'Authorization: Bearer TOKEN'
      ```

      ```ts Node.js
      import { createClient } from "@tursodatabase/api";

      const turso = createClient({
        org: "...",
        token: "",
      });

      const group = await turso.groups.addLocation("default", "ams");
      ```
    </CodeGroup>
  </Step>

  <Step title="Connect to your database">
    You now have a database, distributed across multiple regions that you can connect to using one of the official or experimental SDKs:

    <Snippet file="all-sdks.mdx" />
  </Step>
</Steps>


# Errors



The Turso API will respond with an HTTP status code, and in the event of an error, return an error message in the response body.

| Code  | Description                                                      |
| ----- | ---------------------------------------------------------------- |
| `200` | `OK` — Successful request                                        |
| `401` | `Unauthorized` — Invalid or expired auth token                   |
| `402` | `Payment required` — Check you have an active subscription       |
| `403` | `Forbidden` — You do not have permission to access this resource |
| `409` | `Conflict` — Resource already exists                             |


# Create API Token

POST /v1/auth/api-tokens/{tokenName}
Returns a new API token belonging to a user.

<Warning>
  The `token` in the response is never revealed again. Store this somewhere safe, and never share or commit it to source control.
</Warning>

<RequestExample>
  ```bash cURL
  curl -L -X POST https://api.turso.tech/v1/auth/api-tokens/{tokenName} \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const apiToken = await turso.apiTokens.create("my-token");
  ```
</RequestExample>


# List API Tokens

GET /v1/auth/api-tokens
Returns a list of API tokens belonging to a user.

<RequestExample>
  ```bash cURL
  curl -L https://api.turso.tech/v1/auth/api-tokens \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const apiTokens = await turso.apiTokens.list();
  ```
</RequestExample>


# Revoke API Token

DELETE /v1/auth/api-tokens/{tokenName}
Revokes the provided API token belonging to a user.

<RequestExample>
  ```bash cURL
  curl -L -X DELETE 'https://api.turso.tech/v1/auth/api-tokens/{tokenName}' \
  -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const response = await turso.apiTokens.revoke("my-token");
  ```
</RequestExample>


# Validate API Token

GET /v1/auth/validate
Validates an API token belonging to a user.

<RequestExample>
  ```bash cURL
  curl -L 'https://api.turso.tech/v1/auth/validate' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```ts Node.js
  import { createClient } from "@tursodatabase/api";

  const turso = createClient({
    org: "...",
    token: "",
  });

  const response = await turso.apiTokens.validate("...");
  ```
</RequestExample>


# auth api-tokens list



To list all API tokens for the current organization, run the following command:

```bash
turso auth api-tokens list
```


# auth api-tokens mint



To create a new API token for the current organization, run the following command:

```bash
turso auth api-tokens mint <api-token-name>
```


# auth api-tokens revoke



To revoke an API token for the current organization, run the following command:

```bash
turso auth api-tokens revoke <api-token-name>
```


# auth login



To authenticate the Turso CLI with your account, run the following command:

```bash
turso auth login
```

<Note>
  If you're using Windows with WSL or a remote CI/CD environment, pass the --headless flag.
</Note>

## Flags

| Flag         | Description                                                       |
| ------------ | ----------------------------------------------------------------- |
| `--headless` | Useful when the CLI can't interact with the system's web browser. |


# auth logout



To logout of the Turso CLI, run the following command:

```bash
turso auth logout
```

## Flags

| Flag        | Description                                   |
| ----------- | --------------------------------------------- |
| `-a, --all` | Invalidate all sessions for the current user. |


# auth signup



To sign up for a new Turso account using the CLI, run the following command:

```bash
turso auth signup
```

<Note>
  If you're using Windows with WSL or a remote CI/CD environment, pass the --headless flag.
</Note>

## Flags

| Flag         | Description                                                       |
| ------------ | ----------------------------------------------------------------- |
| `--headless` | Useful when the CLI can't interact with the system's web browser. |


# auth token



You can obtain your current API token that is used to authenticate with the Turso Platform API by running the following command:

```bash
turso auth token
```


# auth whoami



You can obtain the username for the currently logged in user by running the following command:

```bash
turso auth whoami
```


# Authentication



## `login`

The Turso CLI uses an access token to authenticate with Turso. You can login using the command:

```bash
turso auth login
```

This will open a browser window, asking you to log into your account with GitHub.

<Note>
  If you're using Windows with WSL or a remote CI/CD environment, pass the `--headless` flag.
</Note>

Once you're logged in, you can manage your account and databases. You can explore all of the commands via the docs, or by using the `--help` flag for each subcommand:

```bash
turso
```

<Info>
  The Turso CLI requires you to reauthenticate after one week. Don't share your token.
</Info>

## `signup`

If you're new to Turso, you can create an account using the Turso CLI:

```bash
turso auth signup
```

## `logout`

You can logout of the Turso CLI using the `logout` command:

```bash
turso auth logout
```


# contact bookmeeting



You can book a meeting with the Turso team to discuss your project and requirements using the following command:

```bash
turso contact bookmeeting
```

<Info>
  You will be redirected to a webpage where you can select a date and time for the meeting.
</Info>


# contact feedback



You can send feedback to the Turso team by using the following command:

```bash
turso contact feedback
```


# db config attach allow



Allow a database to be attached by other databases:

```bash
turso db config attach allow <database-name>
```


# db config attach disallow



Disallow a database to be attached by other databases:

```bash
turso db config attach disallow <database-name>
```


# db config attach show



Show the attach configuration for a database:

```bash
turso db config attach show <database-name>
```


# db create



You can create a new database in a specific group using the following command:

```bash
turso db create [database-name]
```

<Info>
  The `[database-name]` argument is optional. If you don't provide a name, the Turso team will use the name of your project.
</Info>

<Info>
  If you have more than one group, you will need to pass the `--group` flag.
</Info>

## Flags

| Flag                       | Description                                                                                                                                                                                                                           |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--enable-extensions`      | Enables experimental support for SQLite extensions.                                                                                                                                                                                   |
| `--from-csv`               | Create the database from a csv file.                                                                                                                                                                                                  |
| `--csv-table-name`         | Name of the table in the csv file.                                                                                                                                                                                                    |
| `--from-db`                | Select another database to copy data from.                                                                                                                                                                                            |
| `--timestamp`              | Set a point in time in the past to copy data from the selected database.<br /><br />Must be used with the 'from-db' flag. Must be in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) format like '2023-09-29T10:16:13-03:00' |
| `--from-dump`              | Create the database from a local SQLite dump.                                                                                                                                                                                         |
| `--from-dump-url`          | Create the database from a remote SQLite dump.                                                                                                                                                                                        |
| `--from-file`              | Create the database from a local SQLite3-compatible file.                                                                                                                                                                             |
| `--group`                  | Create the database in the specified group.                                                                                                                                                                                           |
| `--type <regular\|schema>` | The type of database to create. Defaults to to `regular`.                                                                                                                                                                             |
| `--schema <string>`        | The database schema to use ([learn more about multi-db schemas](/features/multi-db-schemas)).                                                                                                                                         |
| `--size-limit`             | The maximum size of the database in bytes. Values with units are also accepted, e.g. 1mb, 256mb, 1gb.                                                                                                                                 |
| `--canary`                 | Use database canary build.                                                                                                                                                                                                            |
| `-w`, `--wait`             | Wait for the database to be ready to receive requests.                                                                                                                                                                                |
| `-h`, `--help`             | Get help for create.                                                                                                                                                                                                                  |

## Examples

The examples below outline the most common use cases for the `db create` command.

### Create database in a specific group

You can create a new database in a specific group using the `--group` flag:

```bash
turso db create [database-name] --group <group-name>
```

### Create database from SQLite file

You can create a new Turso database from an existing SQLite file using the `--from-file` flag:

```bash
turso db create [database-name] --from-file ./path/to/file.db
```

<Info>
  The file size is limited to 2GB.
</Info>

### Create database from SQLite dump

You can create a new database using the output of `.dump` using the `--from-dump` flag:

```bash
turso db create [database-name] --from-dump ./path/to/dump.sql
```

### Create database from another existing database

You can create a new Turso database from an existing database using the `--from-db` flag:

```bash
turso db create [database-name] --from-db <existing-database-name>
```

### Create database from a point in time

You can create a new Turso database from an existing database at a specific point in time using the `--from-db` and `--timestamp` flags:

```bash
turso db create [database-name] --from-db <existing-database-name> --timestamp 2024-01-01T10:10:10-10:00
```

### Create database from a CSV file

You can create a new Turso database from a CSV file using the `--from-csv` flag:

```bash
turso db create [database-name] --from-csv ./path/to/file.csv --csv-table-name <desired-table-name>
```

### Create a database with extensions enabled

You can create a database with experimental support for SQLite [extensions](/libsql#extensions) using the `--enable-extensions` flag:

```bash
turso db create [database-name] --enable-extensions
```

<Note>
  Using `--enable-extensions` will enable extensions on all databases in the group.
</Note>

### Create a database with a schema from a parent database

You can create a database using the schema of another database using the `--schema` flag:

```bash
turso db create child-db --schema parent-db
```

<Note>
  The parent database must be created using the `--type schema` flag.
</Note>


# db destroy



You can destroy a database, including any replicas by using the following command:

```bash
turso db destroy <database-name> [flags]
```

## Flags

| Flag          | Description                            |
| ------------- | -------------------------------------- |
| `-y`, `--yes` | Confirms the destruction the database. |


# db inspect



You can inspect the usage of a database, including the total space used, rows read and written with the following command:

```bash
turso db inspect <database-name>
```

## Flags

| Flag        | Description                                                          |
| ----------- | -------------------------------------------------------------------- |
| `--queries` | Show database query statistics.                                      |
| `--verbose` | Show detailed information, including the location and instance type. |

## Examples

### Top Queries

You can fetch the most executed, resource-intensive SQL statements that have been run against your database using the Turso CLI:

<CodeGroup>
  ```bash Command
  turso db inspect <database-name> --queries
  ```

  ```bash Response
  SELECT * FROM Orders WHERE Status = 'Pending';
  SELECT COUNT(*), CustomerID FROM Orders GROUP BY CustomerID HAVING COUNT(*) > 5;
  SELECT Orders.OrderID, Customers.CustomerName FROM Orders INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID;
  UPDATE Products SET Price = Price * 1.10 WHERE Category = 'Electronics';
  ```
</CodeGroup>


# db list



You can obtain a list of all databases for the current user or organization by running the following command:

```bash
turso db list
```

## Flags

| Flag                       | Description                        |
| -------------------------- | ---------------------------------- |
| `--schema <database-name>` | Filter databases by parent schema. |
| `--group <group-name>`     | Filter databases by group.         |


# db locations



You can fetch a list of [supported locations](/concepts#locations) where databases can be stored and replicated by running the following command:

```bash
turso db locations
```

## Flags

| Flag                     | Description                                                               |
| ------------------------ | ------------------------------------------------------------------------- |
| `-l`, `--show-latencies` | Display latencies from your current location to each of Turso's locations |


# db shell



You can connect directly to a Turso database by using the following command:

```bash
turso db shell <database-name | replica-url> [sql] [flags]
```

## Flags

| Flag                         | Description                                                        |
| ---------------------------- | ------------------------------------------------------------------ |
| `--attach <database-name>`   | List of database names with attach claim to be added to the token. |
| `--instance <instance>`      | Connect to the specified database instance.                        |
| `--location <location-code>` | Connect to the database at the specified location.                 |
| `--proxy <url>`              | The proxy to use when connecting to the database.                  |

## Examples

### Execute SQL

You can execute SQL directly against a database using the shell:

```bash
turso db shell <database-name> "SELECT * FROM users"
```

### Database dump

You can dump the contents of a Turso database using the following command:

```bash
turso db shell <database-name> .dump > dump.sql
```

<Info>
  The `.dump` can be used to rebuild a database and doesn't contain any libSQL or SQLite internal tables.
</Info>

### Load from dump

You can load a dump file into a new database using the following command:

```bash
turso db shell <database-name> < dump.sql
```

### Shell with libSQL server

If you're using `turso dev` locally, you can use the shell by providing the URL to your database:

```bash
turso db shell http://127.0.0.1:8080
```

### Connect using a specific database location

You can connect to a database in a specific location using the `--location` flag:

```bash
turso db shell <database-name> --location nrt
```


# db show



You can obtain details about the database, including the name, ID, libSQL server version, group, size and locations.

```bash
turso db show <database-name> [flags]
```

You can also obtain the different URLs for the database using the following:

## Flags

| Flag              | Description                                                      |
| ----------------- | ---------------------------------------------------------------- |
| `--url`           | Show URL for the database HTTP API.                              |
| `--http-url`      | Show HTTP URL for the database HTTP API.                         |
| `--instance-urls` | Show individual instance URLS for primary and replica instances. |


# db tokens create



You can create a new token that can be used to connect to one database using the command:

```bash
turso db tokens create <database-name> [flags]
```

## Flags

| Flag                 | Description                                                                     |
| -------------------- | ------------------------------------------------------------------------------- |
| `-e`, `--expiration` | The expiration time for a token, can be `never` or a value in days, e.g. `7d` . |
| `-r`, `--read-only`  | Restrict the token to read only access.                                         |

## Examples

The examples below outline the most common use cases for the `db tokens create` command.

### Create a token with read only access

You can create a token with read only access to a database using the following command:

```bash
turso db tokens create <database-name> --read-only
```

### Create a token with a specific expiration time

You can create a token with a specific expiration time using the following command:

```bash
turso db tokens create <database-name> --expiration 7d3h2m1s
```


# db tokens invalidate



You can invalidate all tokens for a database by running the following command:

```bash
turso db tokens invalidate <database-name> [flags]
```

## Flags

| Flag          | Description                                          |
| ------------- | ---------------------------------------------------- |
| `-y`, `--yes` | Confirms the invalidation of all existing db tokens. |

<Warning>
  All tokens in the group that provided database belongs will also be invalidated. This means that all existing tokens will no longer be valid and will need to be regenerated.
</Warning>


# dev





# group create



You can create a new group of databases. Groups belong to a primary region and can be replicated to other regions.

```bash
turso group create <group-name> [flags]
```

<Warning>
  Creating more than one group is limited to Scaler, Pro and Enterprise plans.
</Warning>

<Info>
  Turso will automatically detect the closest region and use that as the primary region. You can override this by specifying the `--location` flag.
</Info>

## Flags

| Flag           | Description                                                                 |
| -------------- | --------------------------------------------------------------------------- |
| `--canary`     | Use database canary build.                                                  |
| `--location`   | Create the group in the specified priary location using a three-digit code. |
| `-w`, `--wait` | Wait for group to be ready before exiting.                                  |


# group destroy



You can destroy a group and all of its databases using the following command:

```bash
turso group destroy <group-name> [flags]
```

## Flags

| Flag          | Description                                                      |
| ------------- | ---------------------------------------------------------------- |
| `-y`, `--yes` | Confirms destroying the group, with all locations and databases. |


# group list



You can obtain a list of all groups, including the primary and replica locations using the following command:

```bash
turso group list
```


# group locations add



You can replicate databases globally by adding locations to a group using the following command:

```bash
turso group locations add <group-name> <location-code> [flags]
```

## Flags

| Flag           | Description                                |
| -------------- | ------------------------------------------ |
| `-w`, `--wait` | Wait for group to be ready before exiting. |


# group locations list



You can obtain a list of all locations that a group belongs to by running the following command:

```bash
turso group locations list <group-name>
```


# group locations remove



You can remove locations from a group using the command below:

```bash
turso group locations remove <group-name> <...location-codes>
```

<Info>
  All database replicas belonging to the provided group will be immediately removed from the locations.
</Info>


# group tokens create



You can create a new token that can be used to connect to any database in the group using the command:

```bash
turso group tokens create <group-name> [flags]
```

## Flags

| Flag                 | Description                                                                     |
| -------------------- | ------------------------------------------------------------------------------- |
| `-e`, `--expiration` | The expiration time for a token, can be `never` or a value in days, e.g. `7d` . |
| `-r`, `--read-only`  | Restrict the token to read only access.                                         |

## Examples

The examples below outline the most common use cases for the `group tokens create` command.

### Create a token with read only access

You can create a token with read only access using the command:

```bash
turso group tokens create <group-name> --read-only
```

### Create a token with a specific expiration time

You can create a token with a specific expiration time using the command:

```bash
turso group tokens create <group-name> --expiration 7d
```


# group tokens invalidate



You can invalidate all tokens for a group by running the command:

```bash
turso group tokens invalidate <group-name> [flags]
```

## Flags

| Flag          | Description                                             |
| ------------- | ------------------------------------------------------- |
| `-y`, `--yes` | Confirms the invalidation of all existing group tokens. |


# group transfer



You can transfer a group (including its databases) to an organization you're an admin or owner of using the following command:

```bash
turso group transfer <group-name> <organization-name> [flags]
```

<Warning>
  Existing database URL and tokens will continue to work, but should update your application to use the new URL and token as soon as possible.
</Warning>

## Flags

| Flag          | Description                                  |
| ------------- | -------------------------------------------- |
| `-y`, `--yes` | Confirms the transfer to a new organization. |


# group unarchive



You can unarchive inactive databases by running the following command:

```bash
turso group unarchive <group-name>
```

<Info>
  Databases get archived after 10 days of inactivity for users on a free plan — [learn more](/features/scale-to-zero).
</Info>


# group update



You can update the group, including all databases the following command:

```bash
turso group update <group-name> [flags]
```

## Flags

| Flag                  | Description                                                                         |
| --------------------- | ----------------------------------------------------------------------------------- |
| `--extensions string` | Enable extensions by passing `all` or `none`.                                       |
| `--version string`    | Specify the version of the group to update to. Values include `latest` or `canary`. |
| `-y`, `--yes`         | Skip confirmation prompt and confirm.                                               |

## Examples

### Update a group to enable all extensions

You can update a group and all its databases to enable `all` extensions:

```bash
turso group update <group-name> --extensions all
```


# Headless Mode



The Turso CLI will automatically attempt to open a browser, or wait for further instructions when interacting with various commands.

You can opt out of this behaviour by passing the `--headless` flag with operations:

```bash
turso auth login --headless
```

<Note>
  If you're using Windows with WSL or a remote CI/CD environment, pass the `--headless` flag.
</Note>


# Help



You can always find a summary of all commands by running the following command:

```bash
turso help
```

You can also find out more about each command, as well as any required or optional arguments by passing the `--help` flag to the command:

```bash
turso auth --help
turso db create --help
```

If you require support integrating Turso into your project, [we can help](/support).


# Installation

Learn how to install the Turso CLI on Mac, Linux and Windows.

## macOS

To install the Turso CLI on macOS, we recommend that you use Homebrew:

```bash
brew install tursodatabase/tap/turso
```

If you don't use Homebrew, you can use the following command to execute a shell script that installs the CLI:

```bash
curl -sSfL https://get.tur.so/install.sh | bash
```

## Linux

Run the following command to execute a shell script that installs the CLI:

```bash
curl -sSfL https://get.tur.so/install.sh | bash
```

## Windows

Installing the Turso CLI on Windows requires that you have [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) installed.

Once WSL is installed, run the following in PowerShell:

```bash
wsl
```

You can then execute the script to install the Turso CLI:

```bash
curl -sSfL https://get.tur.so/install.sh | bash
```

## Verify installation

You must open a new shell to verify the installation with the following command:

```bash
turso
```


# Introduction



The Turso CLI gives you everything you need from the command line to manage your database, database replicas, API tokens, inviting users, and launching the database shell. If you're waiting for a migration to run, there's also a relax command.

You can also programmatically manage your Turso account, including groups, databases, organizations and invites using the [Platform API](/api-reference).

<Steps>
  <Step title="Install">
    Begin by installing the Turso CLI:

    <CodeGroup>
      ```bash macOS
      brew install tursodatabase/tap/turso
      ```

      ```bash Linux
      curl -sSfL https://get.tur.so/install.sh | bash
      ```

      ```bash Windows (WSL)
      curl -sSfL https://get.tur.so/install.sh | bash
      ```
    </CodeGroup>
  </Step>

  <Step title="Authenticate">
    Now signup or login:

    <CodeGroup>
      ```bash Signup
      turso auth signup
      ```

      ```bash Login
      turso auth login
      ```

      ```bash Signup (WSL)
      turso auth signup --headless
      ```

      ```bash Login (WSL)
      turso auth login --headless
      ```
    </CodeGroup>
  </Step>

  <Step title="Operate">
    The Turso CLI provides the following commands:

    | Command                     | Description                                                          |
    | --------------------------- | -------------------------------------------------------------------- |
    | [`auth`](/cli/auth)         | Authenticate and manage API tokens.                                  |
    | [`contact`](/cli/contact)   | Submit your feedback, ideas and create a meeting with the team.      |
    | [`db`](/cli/db)             | Create and manage databases, access tokens and connect to the shell. |
    | `dev`                       | Run Turso [locally](/local-development) for development.             |
    | [`group`](/cli/group)       | Create groups and manage global replicas.                            |
    | [`org`](/cli/org)           | Manage billing and invite memebers.                                  |
    | [`plan`](/cli/plan)         | `overages`, `select`, `show`, `upgrade`                              |
    | [`quickstart`](/quickstart) | Get started with Turso in 5 minutes.                                 |
    | `relax`                     | Take some time out and relax with Turso.                             |
    | `update`                    | Update to the Turso CLI to the latest version with one command.      |
  </Step>
</Steps>


# org billing



To open the billing portal for your organization:

```bash
turso org billing
```


# org create



To create a new organization that you own, run the following command:

```bash
turso org create <name>
```

<Info>
  You will be asked to add a payment method and subscribe to the Scaler plan to successfully create a new organization.
</Info>


# destroy



To delete an existing organization that you own, run the following command:

```bash
turso org destroy <organization-slug>
```

<Info>
  You will need to transfer or delete any existing projects before you can delete an organization. Users cannot also destroy the a personal account or active organization.
</Info>


# org list



To list organizations of which you are the owner or a member, run the following command:

```bash
turso org list
```


# org members add



To add an existing Turso user as a member to the current active organization, run the following command:

```bash
turso org members add <username> [flags]
```

## Flags

| Flag            | Description               |
| --------------- | ------------------------- |
| `-a`, `--admin` | Add the user as an admin. |


# org members invite



To invite someone who isn't already a Turso user to the current active organization, run the following command:

```bash
turso org members invite <email> [flags]
```

## Flags

| Flag            | Description               |
| --------------- | ------------------------- |
| `-a`, `--admin` | Add the user as an admin. |


# org members list



To list all members of the current active organization, run the following command:

```bash
turso org members list
```

<Info>
  This command is only available to active organizations, use [`org switch`](/cli/org/switch) if you're currently authenticated with your personal account.
</Info>


# org members rm



To remove a member from the current organization, use the following command:

```bash
turso org members rm <username>
```


# org switch



To switch the current active organization for the CLI, use the following command:

```bash
turso org switch <organization-slug>
```


# plan overages disable



You can disable overages for the current repository by running the following command:

```bash
turso plan overages disable
```

<Info>
  Any overages that have already been incurred will still be charged.
</Info>


# plan overages enable



You can enable overages for the current repository by running the following command:

```bash
turso plan overages enable
```


# plan select



You can switch your current plan at any time using the command:

```bash
turso plan select
```

<Info>
  You will need to add your credit card details to your account before you can upgrade to a paid plan. [Learn more](https://turso.tech/pricing) about pricing.
</Info>


# plan show



You can show the current plan usage and limits with the command:

```bash
turso plan show
```


# plan upgrade



You can upgrade your account to a paid plan at any time using the command:

```bash
turso plan upgrade
```

<Info>
  You will need to add your credit card details to your account before you can upgrade to a paid plan.
</Info>


# Upgrading

Update the Turso CLI to the latest version to benefit from all the latest features, and fixes.

## macOS

```bash
brew update
brew upgrade
```

## Linux

```bash
turso update
```

## Windows

```bash
turso update
```


# Turso Concepts



## Database

Each database is equipped with its own schema and data, situated in a primary location along with possibly several replica locations within its designated [group](#groups). This setup ensures that the schema and data are seamlessly copied from the primary location to all replica sites in the group.

Databases are identified by a distinct libSQL URL. When accessed through the libSQL client SDKs, this URL directs the client to the database instance that offers the lowest latency, thereby reducing the overall duration of read operations.

<Info>
  Learn more about [data and connections](/data-and-connections).
</Info>

### Schema Database

Turso provides a feature called [Multi-DB Schemas](/features/multi-db-schemas) that let you share schema across many databases in a group. This is useful for creating a multi-tenant application where each tenant has their own database.

## Instance

A database instance represents a single element of a logical database situated at a specific location.

This instance operates under a managed libSQL server setup hosted on an individual machine. Instances belonging to various logical databases within the same [group](#groups) are managed by a single libSQL server process running on the same piece of hardware.

Instances are categorized into two types: primary and replica.

## Groups

All databases are part of a "group", dictating their primary storage location and replication across distinct VMs ([locations](#locations)), each replica (volume) is capped at 100GB. This setup ensures databases share resources yet remain isolated.

<Note>Enterprise plans can have higher limits on storage.</Note>

<Frame caption="A single group with replicas">
  ![Turso Database Groups and Replication](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/concepts/database-group.png)
</Frame>

<Warning>
  Creating more than one group is limited to Scaler, Pro and Enterprise plans.
  You can add additional groups if you have overages enabled.
</Warning>

## Locations

Depending on your chosen cloud provider, Fly or AWS, you can deploy to a variety of locations. Your databases form a [group](#groups) with a primary and optional replica locations. Turso handles synchronization from the primary to replicas automatically across its [data edge](/features/data-edge).

*   **Primary**
    *   All databases have a primary location (region) where data is stored, and can't be changed. You can configure the primary location for groups using the Turso CLI and Turso Platform API.
*   **Replicas**
    *   Databases can be replicated to other regions closer to your users by adding more locations to the group your database belongs to.

<Accordion title="Fly locations">
  | Code  | Location                     |
  | ----- | ---------------------------- |
  | `ams` | Amsterdam, Netherlands       |
  | `arn` | Stockholm, Sweden            |
  | `bog` | Bogotá, Colombia             |
  | `bos` | Boston, Massachusetts (US)   |
  | `cdg` | Paris, France                |
  | `den` | Denver, Colorado (US)        |
  | `dfw` | Dallas, Texas (US)           |
  | `ewr` | Secaucus, NJ (US)            |
  | `fra` | Frankfurt, Germany           |
  | `gdl` | Guadalajara, Mexico          |
  | `gig` | Rio de Janeiro, Brazil       |
  | `gru` | São Paulo, Brazil            |
  | `hkg` | Hong Kong, Hong Kong         |
  | `iad` | Ashburn, Virginia (US)       |
  | `jnb` | Johannesburg, South Africa   |
  | `lax` | Los Angeles, California (US) |
  | `lhr` | London, United Kingdom       |
  | `mad` | Madrid, Spain                |
  | `mia` | Miami, Florida (US)          |
  | `nrt` | Tokyo, Japan                 |
  | `ord` | Chicago, Illinois (US)       |
  | `otp` | Bucharest, Romania           |
  | `qro` | Querétaro, Mexico            |
  | `scl` | Santiago, Chile              |
  | `sea` | Seattle, Washington (US)     |
  | `sin` | Singapore, Singapore         |
  | `sjc` | San Jose, California (US)    |
  | `syd` | Sydney, Australia            |
  | `waw` | Warsaw, Poland               |
  | `yul` | Montreal, Canada             |
  | `yyz` | Toronto, Canada              |
</Accordion>

<Info>
  You can fetch the list of supported locations as JSON when building with the [Platform API](/api-reference/locations) or using the [Turso CLI](/cli/db/locations).
</Info>


# Data & Connections

Learn how data consistency and connections work with Turso databases.

Turso, an extension of [libSQL](/libsql) (a SQLite fork), modifies the consistency model due to its network-accessible and replicated nature, deviating from SQLite's strictly serializable standard.

## Establishing Connections

Database operations begin with a client establishing either an HTTP or websocket connection to a server instance. Following this, an internal SQLite database connection is set up within the server to facilitate the operations.

## Data Consistency

Database operations are tightly controlled to maintain order and data integrity, with primary instances handling all writes in a serialized manner and replicas managing local reads.

### Primary Database Operations

*   All operations are linearizable, maintaining an ordered history.
*   Writes are fully serialized, with subsequent writes awaiting transaction completion.
*   Users should exercise caution with long-running or abandoned transactions to prevent blocking other writes.

### Replica Operations & Reads

*   **Forwarding Writes to the Primary:**
    *   All writes are forwarded to the primary, ensuring serialized application.
*   **Replication Process:**
    *   Changes from the primary are eventually propagated to each replica, with a latency of 200-300ms.
    *   New connections may encounter stale data until a write operation updates the replication index.
    *   Replicas do not guarantee immediate reflection of primary's changes, leading to potential data differences across replicas.
    *   Monotonic reads are maintained, ensuring read operations retrieve data newer than previously accessed data on the same instance.
*   **Immediate Read-After-Write Consistency:**
    *   Replication index tracking enables immediate read-after-write consistency.
    *   Clients track replication frames to ensure awareness of the most recent data state across replicas.
    *   Replicas manage requests based on the client's replication index, ensuring consistent data access.
    *   Developers can utilize a driver to track replication frames, guaranteeing consistency between read and write operations.

## Transactional Consistency

*   Transactions in libSQL, encompassing both batch and interactive transactions, adhere to SQLite's transaction semantics.
*   libSQL provides snapshot isolation for read operations, ensuring immediate visibility of writes within the same process. This guarantees serializability and isolation from other transactions.


# AI & Embeddings

Vector Similarity Search is built into Turso and libSQL Server as a native feature.

Turso and libSQL enables vector search capability without an extension.

<Snippet file="technical-preview-banner.mdx" />

<Note>
  Full support for vector search in the Turso platform starts from version `v0.24.24` <br />
  (use the `turso group show <group-name>` command to check the group version).
</Note>

## How it works

*   Create a table with one or more vector columns (e.g. `FLOAT32`)
*   Provide vector values in binary format or convert text representation to binary using the appropriate conversion function (e.g. `vector32(...)`)
*   Calculate vector similarity between vectors in the table or from the query itself using dedicated vector functions (e.g. `vector_distance_cos`)
*   Create a special vector index to speed up nearest neighbors queries (use the `libsql_vector_idx(column)` expression in the `CREATE INDEX` statement to create vector index)
*   Query the index with the special `vector_top_k(idx_name, q_vector, k)` [table-valued function](https://www.sqlite.org/vtab.html#table_valued_functions)

# Vectors

### Types

LibSQL uses the native SQLite BLOB [storage class](https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes) for vector columns. To align with SQLite [affinity rules](https://www.sqlite.org/datatype3.html#determination_of_column_affinity), all type names have two alternatives: one that is easy to type and another with a `_BLOB` suffix that is consistent with affinity rules.

<Info>
  We suggest library authors use type names with the `_BLOB` suffix to make
  results more generic and universal. For regular applications, developers can
  choose either alternative, as the type name only serves as a **hint** for
  SQLite and external extensions.
</Info>

<Info>
  As LibSQL does not introduce a new storage class, all metadata about vectors
  is also encoded in the `BLOB` itself. This comes at the cost of a few bytes
  per row but greatly simplifies the design of the feature.
</Info>

The table below lists six vector types currently supported by LibSQL. Types are listed from more precise and storage-heavy to more compact but less precise alternatives (the number of dimensions in vector $D$ is used to estimate storage requirements for a single vector).

| Type name                   | Storage (bytes)                 | Description                                                                                                                                                                                        |
| --------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FLOAT64` \| `F64_BLOB`     | $8D + 1$                        | Implementation of [IEEE 754 double precision format](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) for 64-bit floating point numbers                                       |
| `FLOAT32` \| `F32_BLOB`     | $4D$                            | Implementation of [IEEE 754 single precision format](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) for 32-bit floating point numbers                                       |
| `FLOAT16` \| `F16_BLOB`     | $2D + 1$                        | Implementation of [IEEE 754-2008 half precision format](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) for 16-bit floating point numbers                                      |
| `FLOATB16` \| `FB16_BLOB`   | $2D + 1$                        | Implementation of [bfloat16 format](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format) for 16-bit floating point numbers                                                                |
| `FLOAT8` \| `F8_BLOB`       | $D + 14$                        | LibSQL specific implementation which compresses each vector component to single `u8` byte `b` and reconstruct value from it using simple transformation: $\texttt{shift} + \texttt{alpha} \cdot b$ |
| `FLOAT1BIT` \| `F1BIT_BLOB` | $\lceil \frac{D}{8} \rceil + 3$ | LibSQL-specific implementation which compresses each vector component down to 1-bit and packs multiple components into a single machine word, achieving a very compact representation              |

<Info>
  For most applications, the `FLOAT32` type should be a good starting point, but
  you may want to explore more compact options if your table has a large number
  of rows with vectors.
</Info>

<Info>
  While `FLOAT16` and `FLOATB16` use the same amount of storage, they provide
  different trade-offs between speed and accuracy. Generally, operations over
  `bfloat16` are faster but come at the expense of lower precision.
</Info>

### Functions

To work with vectors, LibSQL provides several functions that operate in the vector domain. Each function understands vectors in binary format aligned with the six types described above or in text format as a single JSON array of numbers.

Currently, LibSQL supports the following functions:

| Function name                                                                      | Description                                                                                                                                                                  |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vector64` \| `vector32` \| `vector16` \| `vectorb16` \| `vector8` \| `vector1bit` | Conversion function shiwh accepts valid vector and convert it to the corresponding target type                                                                               |
| `vector`                                                                           | Alias for `vector32` conversion function                                                                                                                                     |
| `vector_extract`                                                                   | Extraction function which accepts valid vector and return its text representation                                                                                            |
| `vector_distance_cos`                                                              | Cosine distance (1 - [cosine similarity](https://en.wikipedia.org/wiki/Cosine_similarity)) function which operates over vector of **same type** with **same dimensionality** |
| `vector_distance_l2`                                                               | Euclidian distance function which operates over vector of **same type** with **same dimensionality**                                                                         |

### Vectors usage

<Steps>
  <Step title="Create a table">
    Begin by declaring a column used for storing vectors with the `F32_BLOB` datatype:

    ```sql
    CREATE TABLE movies (
      title    TEXT,
      year     INT,
      full_emb F32_BLOB(4), -- 4-dimensional f32 vector
    );
    ```

    The number in parentheses `(4)` specifies the dimensionality of the vector. This means each vector in this column will have exactly 4 components.
  </Step>

  <Step title="Generate and insert embeddings">
    Once you generate embeddings for your data (via an LLM), you can insert them into your table:

    ```sql
    INSERT INTO movies (title, year, embedding)
    VALUES
      ('Napoleon', 2023, vector32('[0.800, 0.579, 0.481, 0.229]')),
      ('Black Hawk Down', 2001, vector32('[0.406, 0.027, 0.378, 0.056]')),
      ('Gladiator', 2000, vector32('[0.698, 0.140, 0.073, 0.125]')),
      ('Blade Runner', 1982, vector32('[0.379, 0.637, 0.011, 0.647]'))
    ```

    Popular tools like [LangChain](https://www.langchain.com), [Hugging Face](https://huggingface.co) or [OpenAI](https://turso.tech/blog/how-to-generate-and-store-openai-vector-embeddings-with-turso) can be used to generate embeddings.
  </Step>

  <Step title="Peform a vector similarity search">
    You can now write queries combining vectors and standard SQLite data:

    ```sql
    SELECT title,
           vector_extract(embedding),
           vector_distance_cos(embedding, vector32('[0.064, 0.777, 0.661, 0.687]'))
    FROM movies
    ORDER BY
           vector_distance_cos(embedding, vector32('[0.064, 0.777, 0.661, 0.687]'))
    ASC;
    ```
  </Step>
</Steps>

### Understanding Distance Results

The `vector_distance_cos` function calculates the cosine distance, which is defined at:

*   Cosine Distance = 1 — [Cosine Similarity](https://en.wikipedia.org/wiki/Cosine_similarity)

The cosine distance ranges from 0 to 2, where:

*   A distance close to 0 indicates that the vectors are nearly identical or exactly matching.
*   A distance close to 1 indicates that the vectors are orthogonal (perpendicular).
*   A distance close to 2 indicates that the vectors are pointing in opposite directions.

<Note>
  Very small negative numbers close to zero (for example, `-10^-14`) may
  occasionally appear due to floating-point arithmetic precision. These should
  be interpreted as effectively zero, indicating an exact or near-exact match
  between vectors.

  ```sql
  SELECT vector_distance_cos('[1000]', '[1000]');
  -- Output: -2.0479999918166e-09
  ```
</Note>

### Vector Limitations

*   Euclidian distance is **not supported** for 1-bit `FLOAT1BIT` vectors
*   LibSQL can only operate on vectors with no more than 65536 dimensions

## Indexing

Nearest neighbors (NN) queries are popular for various AI-powered applications ([RAG](https://en.wikipedia.org/wiki/Retrieval-augmented_generation) uses NN queries to extract relevant information, and recommendation engines can suggest items based on embedding similarity).

LibSQL implements [DiskANN](https://turso.tech/blog/approximate-nearest-neighbor-search-with-diskann-in-libsql) algorithm in order to speed up approximate neareast neighbors queries for tables with vector colums.

<Note>
  The DiskANN algorithm trades search accuracy for speed, so LibSQL queries may
  return slightly suboptimal neighbors for tables with a large number of rows.
</Note>

### Vector Index

LibSQL introduces a custom index type that helps speed up nearest neighbors queries against a fixed distance function (cosine similarity by default).

From a syntax perspective, the vector index differs from ordinary application-defined B-Tree indices in that it must wrap the vector column into a `libsql_vector_idx` marker function like this

```sql
CREATE INDEX movies_idx ON movies (libsql_vector_idx(embedding));
```

<Note>
  Vector index works only for column with one of the vector types described
  above
</Note>

The vector index is fully integrated into the LibSQL core, so it inherits all operations and most features from ordinary indices:

*   An index created for a table with existing data will be automatically populated with this data
*   All updates to the base table will be **automatically** reflected in the index
*   You can rebuild index from scratch using `REINDEX movies_idx` command
*   You can drop index with `DROP INDEX movies_idx` command
*   You can create [partial](https://www.sqlite.org/partialindex.html) vector index with a custom filtering rule:

```sql
CREATE INDEX movies_idx ON movies (libsql_vector_idx(embedding))
WHERE year >= 2000;
```

### Query

At the moment vector index must be queried **explicitly** with special `vector_top_k(idx_name, q_vector, k)` [table-valued function](https://www.sqlite.org/vtab.html#table_valued_functions). The function accepts index name, query vector and amount of neighbors to return. This function search for `k` approximate nearest neighbors and return `ROWID` of these rows or `PRIMARY KEY` if base index [do not have ROWID](https://www.sqlite.org/withoutrowid.html).

In order for table-valued function to work query vector **must** have same vector type and same dimensionality.

### Settings

LibSQL vector index optionally can accept settings which must be specified as a variadic parameters of the `libsql_vector_idx` function as a strings in the format `key=value`:

```sql
CREATE INDEX movies_idx
ON movies(libsql_vector_idx(embedding, 'metric=l2', 'compress_neighbors=float8'));
```

At the moment LibSQL supports following settings:

| Setting key          | Value type                                                          | Description                                                                                                                                                                                                                                                                              |
| -------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `metric`             | `cosine` \| `l2`                                                    | Which distance function to use for building index. <br /> Default: `cosine`                                                                                                                                                                                                              |
| `max_neighbors`      | positive integer                                                    | How many neighbors to store for every node in the DiskANN graph. The lower the setting -- the less storage index will use in exchange to search precision. <br /> Default: $3 \sqrt{D}$ where $D$ -- dimensionality of vector column                                                     |
| `compress_neighbors` | `float1bit`\|`float8`\|<br />`float16`\|`floatb16`\|<br />`float32` | Which vector type must be used to store neighbors for every node in the DiskANN graph. The more compact vector type is used for neighbors -- the less storage index will use in exchange to search precision. <br /> Default: **no comperssion** (neighbors has same type as base table) |
| `alpha`              | positive float $\geq 1$                                             | "Density" parameter of general sparse neighborhood graph build during DiskANN algorithm. The lower parameter -- the more sparse is DiskANN graph which can speed up query speed in exchange to lower search precision. <br />Default: `1.2`                                              |
| `search_l`           | positive integer                                                    | Setting which limits amount of neighbors visited during vector search. The lower the setting -- the faster will be search query in exchange to search precision. <br />Default: `200`                                                                                                    |
| `insert_l`           | positive integer                                                    | Setting which limits amount of neighbors visited during vector insert. The lower the setting -- the faster will be insert query in exchange to DiskANN graph navigability properties. <br />Default: `70`                                                                                |

<Note>
  Vector index for column of type `T1` with `max_neighbors=M` and
  `compress_neighbors=T2` will approximately use $\texttt{N} (Storage(\texttt   {T1}) + \texttt{M} \cdot Storage(\texttt{T2}))$ storage bytes for `N` rows.
</Note>

### Index usage

<Steps>
  <Step title="Create a table">
    Begin by declaring a column used for storing vectors with the `F32_BLOB` datatype:

    ```sql
    CREATE TABLE movies (
      title    TEXT,
      year     INT,
      full_emb F32_BLOB(4), -- 4-dimensional f32 vector
    );
    ```

    The number in parentheses `(4)` specifies the dimensionality of the vector. This means each vector in this column will have exactly 4 components.
  </Step>

  <Step title="Generate and insert embeddings">
    Once you generate embeddings for your data (via an LLM), you can insert them into your table:

    ```sql
    INSERT INTO movies (title, year, embedding)
    VALUES
      ('Napoleon', 2023, vector32('[0.800, 0.579, 0.481, 0.229]')),
      ('Black Hawk Down', 2001, vector32('[0.406, 0.027, 0.378, 0.056]')),
      ('Gladiator', 2000, vector32('[0.698, 0.140, 0.073, 0.125]')),
      ('Blade Runner', 1982, vector32('[0.379, 0.637, 0.011, 0.647]'))
    ```

    Popular tools like [LangChain](https://www.langchain.com), [Hugging Face](https://huggingface.co) or [OpenAI](https://turso.tech/blog/how-to-generate-and-store-openai-vector-embeddings-with-turso) can be used to generate embeddings.
  </Step>

  <Step title="Create an Index">
    Create an index using the `libsql_vector_idx` function:

    ```sql
    CREATE INDEX movies_idx ON movies(libsql_vector_idx(embedding));
    ```

    This creates an index optimized for vector similarity searches on the `embedding` column.

    <Note>
      The `libsql_vector_idx` marker function is **required** and used by libSQL to
      distinguish `ANN`-indices from ordinary B-Tree indices.
    </Note>
  </Step>

  <Step title="Query the indexed table">
    ```sql
    SELECT title, year
    FROM vector_top_k('movies_idx', vector32('[0.064, 0.777, 0.661, 0.687]'), 3)
    JOIN movies ON movies.rowid = id
    WHERE year >= 2020;
    ```

    This query uses the `vector_top_k` [table-valued function](https://www.sqlite.org/vtab.html#table_valued_functions) to efficiently find the top 3 most similar vectors to `[0.064, 0.777, 0.661, 0.687]` using the index.
  </Step>
</Steps>

### Index limitations

*   Vector index works only for tables **with** `ROWID` or with singular `PRIMARY KEY`. Composite `PRIMARY KEY` without `ROWID` is not supported


# Attach Database

Attach and read data across multiple databases.

The `ATTACH` statement enables you to link multiple databases within a single transaction, which is ideal for:

*   Organizing data in a modular way
*   Streamlining data access and enhancing scalability
*   Aggregating data

## How it works

1.  You enable the `ATTACH` feature on the databases you want to connect to.
2.  You retrieve the **Database ID** for the database you want to `ATTACH`.
3.  You connect to the database
    *   **CLI**: `--attach` flag to automatically create a token with the correct permissions.
    *   **SDK**: Create a token with the `attach` permission for the database you want to attach.
4.  You invoke `ATTACH` to connect to the other databases within the database shell or SDK.

## Usage

You can use the `ATTACH` statement to connect to other databases within a transaction using the CLI, or libSQL SDK. Once attached, you can query the attached databases as if they were part of the current database using the assigned alias.

### Turso CLI

Make sure you have the [Turso CLI](/cli/installation) installed, and [logged in](/cli/auth/login).

<Steps>
  <Step title="Enable attach on required databases">
    You will first need to enable the `ATTACH` feature on the database(s) you want to attach:

    ```bash
    turso db config attach allow <database-name>
    ```
  </Step>

  <Step title="Retrieve Database ID">
    You now need to retrieve the **Database ID** for the database you want to `ATTACH`:

    ```bash
    turso db show <database-name>
    ```
  </Step>

  <Step title="Connect to any database with attach">
    Now pass the names of the databases via the `--attach` flag when connecting to your database(s):

    ```bash
    turso db shell <database-name> --attach <...database-name(s)>
    ```
  </Step>

  <Step title="ATTACH">
    Now once connected to the database you can invoke an `ATTACH` statement to connect the other database(s):

    ```sql
    ATTACH "<database-id>" AS my_db;
    ```
  </Step>

  <Step title="Query">
    Execute a query using the alias for any attached database(s):

    ```sql
    SELECT * FROM my_db.my_table;
    ```
  </Step>
</Steps>

### libSQL SDKs

You can use one of the libSQL client SDKs with [TypeScript](/sdk/ts), [Rust](/sdk/rust), [Go](/sdk/go), [Python](/sdk/python), or over [HTTP](/sdk/http).

<Steps>
  <Step title="Enable attach on required databases">
    You will first need to enable the `ATTACH` feature on the database(s) you want to attach:

    ```bash
    turso db config attach allow <database-name>
    ```
  </Step>

  <Step title="Retrieve Database ID">
    You now need to retrieve the **Database ID** for the database you want to `ATTACH`:

    ```bash
    turso db show <database-name>
    ```
  </Step>

  <Step title="Create token with ATTACH permissions">
    Now create a token for the libSQL client with the `attach` permission for the database you want to attach:

    ```bash
    turso db tokens create <database-name> --attach <another-database-name>
    ```
  </Step>

  <Step title="Connect to any database with ATTACH">
    Use a [Client SDK](/sdk) to attach the desired database within a read transaction:

    <CodeGroup>
      ```ts @libsql/client
      import { createClient } from "@libsql/client";

      const client = createClient({
        syncUrl: "libsql://...",
        authToken: "...",
      });

      const txn = await db.transaction("read");

      await txn.execute('ATTACH "<database-id>" AS my_db');

      const rs = await txn.execute("SELECT * FROM my_db.my_table");
      ```
    </CodeGroup>
  </Step>
</Steps>

## Things to know

*   You can only attach databases that have the `attach` feature enabled.
*   You can only attach databases belonging to a group, and in the same group.
*   There is a maximum of 10 databases that can be attached to a single transaction.
*   The attached databases are read only.
*   `ATTACH` statement can be used only within transactions.
*   `ATTACH` doesn't support [Embedded Replicas](/features/embedded-replicas)


# Branching



A branch is a separate database instance that is created from an existing database. You can also create a branch from a [point-in-time](/features/point-in-time-recovery) snapshot of a database. Branches are useful for development and testing, because they allow you to make changes to the database without affecting the original database.

## How it works

1.  You create a new database from an existing database using the CLI or API.
2.  You connect to the new database using the group API token.
3.  Make changes to the new schema using a migration tool (optional).
4.  Apply the changes to the original database using a migration tool when merging using a GitHub Action (optional).
5.  Delete the database when you no longer need it.

## Usage

You can create a new database from an existing database using the CLI or API:

<CodeGroup>
  ```bash CLI
  turso db create my-new-database-branch --from-db my-existing-database
  ```

  ```bash Platform API
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "name": "new-database",
        "group": "default",
        "seed": {
          "type:": "database",
          "name": "my-existing-database"
        }
    }'
  ```
</CodeGroup>

Refer to the following references for more details about all arguments:

<CardGroup>
  <Card horizontal title="CLI Reference" icon="terminal" href="/cli/db/create" />

  <Card horizontal title="API Reference" icon="code" href="/api-reference/databases/create" />
</CardGroup>

## Things to know

*   Database branches are completely separate from the original database. This means that you need to handle merging any schema changes or data manually using a migration tool.
*   You will need to [create a new token](/cli/db/tokens/create) (or use a group token) to connect to the new database.
*   You will need to manually delete the database branch when you no longer need it.
*   Branches count towards your plan's database quota.

## CI/CD

Automating branching is useful for creating a new database for each pull request. This allows you to test changes without affecting the original database.

Here's an example of what that might look like using the [Platform API](/api-reference/databases/create):

```yml .github/workflows/create-database-branch.yml
name: Create Database
on: create

jobs:
  triggerAPI:
    runs-on: ubuntu-latest
    steps:
      - name: Generate Branch Name
        id: branch_name
        run: |
          BRANCH_NAME=$(echo "${{ github.ref_name }}" | tr -cd '[:alnum:]' | sed 's/./\L&/g' | cut -c 1-32)
          echo "::set-output name=branch_name::$BRANCH_NAME"
      - name: Create Database
        run: |
          curl -X POST \
          -H "Authorization: Bearer ${{ secrets.API_TOKEN }}" \
          -H "Content-Type: application/json" \
          -d '{"name": "${{ steps.branch_name.outputs.branch_name }}", "group": "default", "seed": {"type": "database", "name": "${{ secrets.DATABASE_NAME }}"} }' \
          "https://api.turso.tech/v1/organizations/${{ secrets.ORGANIZATION_NAME }}/databases"
```


# Data Edge

Allow your users to reach local replicas of your database, wherever they are.

In the realm of data management, each millisecond of latency is critical. That's why Turso offers over [30 locations](/concepts#locations) for data storage and replication, ensuring minimal delay in data access.

For those seeking the ultimate in speed, Turso enables the [embedding of databases](/features/embedded-replicas) directly within your application on the same node. This configuration eliminates inter-regional request hopping, effectively bringing latency down to zero.

<iframe src="https://www.youtube.com/embed/DyO4OP5v0IM" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen className="w-full aspect-video" />

## How it works

1.  You create a database in a primary location
2.  You add additional locations where data should be replicated
3.  You query a single URL that automatically routes to the nearest edge

<Info>
  Turso automatically handles keeping replicas updated — [learn more](/data-and-connections).
</Info>

## Add replica location

You can add locations to your database group using the [Turso CLI](/cli/group/locations/add) or [Platform API](/api-reference/groups/add-location):

<CodeGroup>
  ```bash CLI
  turso group locations add <group-name> <location-code>
  ```

  ```bash Platform API
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
    -H 'Authorization: Bearer TOKEN'
  ```
</CodeGroup>

## Remove replica location

You can remove locations from your database group using the [Turso CLI](/cli/group/locations/remove) or [Platform API](/api-reference/groups/remove-location):

<CodeGroup>
  ```bash CLI
  turso group locations remove <group-name> <...location-codes>
  ```

  ```bash Platform API
  curl -L -X DELETE 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
    -H 'Authorization: Bearer TOKEN'
  ```
</CodeGroup>


# Embedded Replicas



Turso's embedded replicas are a game-changer for SQLite, making it more flexible and suitable for various environments. This feature shines especially for those using VMs or VPS, as it lets you replicate a Turso database right within your applications without needing to relying on Turso's [edge network](/features/data-edge). For mobile applications, where stable connectivity is a challenge, embedded replicas are invaluable as they allow uninterrupted access to the local database.

Embedded replicas provide a smooth switch between local and remote database operations, allowing the same database to adapt to various scenarios effortlessly. They also ensure speedy data access by syncing local copies with the remote database, enabling microsecond-level read operations — a significant advantage for scenarios demanding quick data retrieval.

## How it works

1.  You configure a local file to be your main database.

    *   The `url` parameter in the client configuration.

2.  You configure a remote database to sync with.

    *   The `syncUrl` parameter in the client configuration.

3.  You read from a database:

    *   Reads are always served from the local replica configured at `url`.

4.  You write to a database:

    *   Writes are always sent to the remote primary database configured at `syncUrl`.
    *   Any write transactions with reads are also sent to the remote primary database.
    *   Once the write is successful, the local database is updated with the changes automatically (read your own writes — can be disabled).

### Periodic sync

You can automatically sync data to your embedded replica using the periodic sync interval property. Simply pass the `syncInterval` parameter when instantiating the client:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: "file:path/to/db-file.db",
  authToken: "...",
  syncUrl: "...",
  syncInterval: 60,
});
```

### Read your writes

Embedded Replicas also will guarantee read-your-writes semantics. What that means in practice is that after a write returns successfully, the replica that initiated the write will always be able to see the new data right away, even if it never calls `sync()`.

Other replicas will see the new data when they call `sync()`, or at the next sync period, if [Periodic Sync](#periodic-sync) is used.

![Read your writes](https://mintlify.s3-us-west-1.amazonaws.com/turso/features/embedded-replicas/read-your-writes.png)

### Encryption at rest

Embedded Replicas support encryption at rest with one of the libSQL client SDKs. Simply pass the `encryptionKey` parameter when instantiating the client:

<CodeGroup>
  <Snippet file="encryption-at-rest-typescript.mdx" />

  <Snippet file="encryption-at-rest-golang.mdx" />

  <Snippet file="encryption-at-rest-rust.mdx" />

  <Snippet file="encryption-at-rest-python.mdx" />

  <Snippet file="encryption-at-rest-flutter.mdx" />
</CodeGroup>

<Note>The encryption key used should be generated and managed by you.</Note>

## Usage

To use embedded replicas, you need to create a client with a `syncUrl` parameter. This parameter specifies the URL of the remote Turso database that the client will sync with:

<CodeGroup>
  ```ts TypeScript
  import { createClient } from "@libsql/client";

  const client = createClient({
    url: "file:replica.db",
    syncUrl: "libsql://...",
    authToken: "...",
  });
  ```

  ```go Go
  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()
  }
  ```

  ```rust Rust
  use libsql::{Builder};

  let build = Builder::new_remote_replica("file:replica.db", "libsql://...", "...")
     .build()
     .await?;
  let client = build.connect()?;
  ```
</CodeGroup>

You can sync changes from the remote database to the local replica manually:

<CodeGroup>
  ```ts TypeScript
  await client.sync();
  ```

  ```go Go
  if err := connector.Sync(); err != nil {
    fmt.Println("Error syncing database:", err)
  }
  ```

  ```rust Rust
  client.sync().await?;
  ```
</CodeGroup>

<br />

<Note>
  You should call `.sync()` in the background whenever your application wants to sync the remote and local embedded replica. For example, you can call it every 5 minutes or every time the application starts.
</Note>

## Things to know

*   Do not open the local database while the embedded replica is syncing. This can lead to data corruption.
*   In certain contexts, such as serverless environments without a filesystem, you can't use embedded replicas.
*   There are a couple scenarios where you may sync more frames than you might
    expect.
    *   A write that causes the internal btree to split at any node would cause many
        new frames to be written to the replication log.
    *   A server restart that left the on-disk wal in dirty state would regenerate
        the replication log and sync additional frames.
    *   Removing/invalidating the local files on disk could cause the embedded
        replica to re-sync from scratch.
*   One frame equals 4kB of data (one on disk page frame), so if you write a 1
    byte row, it will always show up as a 4kB write since that is the unit in
    which libsql writes with.

## Deployment Guides

<CardGroup cols={2}>
  <Card href="/features/embedded-replicas/with-fly" title="Turso + Fly">
    Deploy a JavaScript project with Embedded Replicas to Fly.io
  </Card>

  <Card href="/features/embedded-replicas/with-koyeb" title="Turso + Koyeb">
    Deploy a JavaScript/Rust project with Embedded Replicas to Koyeb
  </Card>

  <Card href="/features/embedded-replicas/with-railway" title="Turso + Railway">
    Deploy a JavaScript/Rust project with Embedded Replicas to Railway
  </Card>

  <Card href="/features/embedded-replicas/with-render" title="Turso + Render">
    Deploy a JavaScript project with Embedded Replicas to Render
  </Card>

  <Card href="/features/embedded-replicas/with-akamai" title="Turso + Linode by Akamai">
    Deploy a JavaScript/Rust project with Embedded Replicas to Akamai
  </Card>
</CardGroup>


# Turso + Linode by Akamai

Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Akamai](https://www.linode.com/).

![Akamai banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/akamai-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Akamai account - [create one](https://login.linode.com/signup)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step>
    Fork one of the following embedded replica projects from GitHub

    <CardGroup cols={2}>
      <Card title="My Expenses Tracker - (Elysia + Bun)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-js">
        See the full source code
      </Card>

      <Card title="Web Traffic API - (Rust)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-rust">
        See the full source code
      </Card>
    </CardGroup>
  </Step>

  <Step title="Set up a Linode server">
    Configure and create a new linode. Then, [set up SSH authentication](https://www.linode.com/docs/guides/use-public-key-authentication-with-ssh/) to securely access the Linode server from your terminal.

    Prepare the newly created linode server environment by accessing and set it up for Rust/JavaScript development depending on the project you forked earlier. Install and set up [Git](https://git-scm.com/) too.
  </Step>

  <Step title="Transfer project to Linode server">
    SSH into your server, clone the project from GitHub, and follow its README instructions to set it up.
  </Step>

  <Step title="Deploy">
    Build, run the project, and set up load balancing for it.
    [pm2](https://www.npmjs.com/package/pm2) is one of the good candidates out there with built-in load balancing, log monitoring, and bug/exception alerts.

    <Info>
      You can go with your favorite options for where to buy domains, reverse proxy setup, and SSL certificates. [Caddy](https://caddyserver.com/) is another good option here.
    </Info>
  </Step>
</Steps>


# Embedded Replicas on Fly

Deploy a JavaScript app using [Turso embedded replicas](/features/embedded-replicas) to [Fly.io](https://www.fly.io/).

![Koyeb banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/fly-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   [Install the Fly.io CLI](https://fly.io/docs/hands-on/install-flyctl/)

<Steps>
  <Step title="Locate your application">
    You should have an application ready using your Turso database that you want to deploy to Fly.
  </Step>

  <Step title="Launch with Fly">
    Using the Fly CLI, launch it:

    ```bash
    fly launch
    ```

    Your application will automatically deploy to Fly, but we're not ready yet.
  </Step>

  <Step title="Create a shared volume">
    Now create a volume that will be used to store the embedded replica(s):

    ```bash
    fly volumes create libsql_data
    ```
  </Step>

  <Step title="Mount and configure volumes">
    The files `fly.toml` and `Dockerfile` created created when you launched previously.

    Update `fly.toml` this file to mount the new volume:

    ```toml
    [[mounts]]
    source = "libsql_data"
    destination = "/app/data"
    ```

    Then inside `Dockerfile`, make sure you install and update `ca-certificates`:

    ```dockerfile
    RUN apt-get update -qq && \
        apt-get install -y ca-certificates && \
        update-ca-certificates
    ```

    Make sure to also add the following line after any `COPY` commands to copy the certificates:

    ```dockerfile
    COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
    ```
  </Step>

  <Step title="Configure the libSQL client">
    You will want to change the `url` to point to a local file, and set the `syncUrl` to be your Turso database URL:

    ```ts
    import { createClient } from "@libsql/client";

    const client = createClient({
      url: "file:./app/data/local.db",
      syncUrl: process.env.TURSO_DATABASE_URL,
      authToken: process.env.TURSO_AUTH_TOKEN,
      syncInterval: 60,
    });
    ```
  </Step>

  <Step title="Deploy your updated app">
    ```bash
    fly deploy
    ```
  </Step>
</Steps>


# Turso + Koyeb

Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Koyeb](https://www.koyeb.com/).

![Koyeb banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/koyeb-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Koyeb account - [create one](https://app.koyeb.com/)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step>
    Fork one of the following embedded replica project from GitHub

    <CardGroup cols={2}>
      <Card title="My Expenses Tracker - (Elysia + Bun)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-js">
        See the full source code
      </Card>

      <Card title="Web Traffic API - (Rust)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-rust">
        See the full source code
      </Card>
    </CardGroup>

    <Note>
      Or, you can:

      <Card title="Deploy to Koyeb with a single-click" href="https://app.koyeb.com/deploy?name=er-with-js&type=git&repository=tursodatabase/embedded-replicas-with-js&branch=main&env[PORT]=8000&env[TURSO_DATABASE_URL]=REPLACE_ME&env[TURSO_AUTH_TOKEN]=REPLACE_ME&env[LOCAL_DB]=file:expenses.db" />
    </Note>
  </Step>

  <Step title="Add a new Koyeb app">
    1.  Create a new app in the Koyeb control panel.

    2.  Select GitHub as the deployment option.

    3.  Import the GitHub project to Koyeb.
  </Step>

  <Step title="Fill in the environment variables on Koyeb's deploy page">
    ![Koyeb deploy page - environment variables](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/koyeb-env-variables.png)
  </Step>

  <Step title="Deploy">
    Click the **Deploy** button at the bottom to deploy your web service.
  </Step>
</Steps>


# Turso + Railway

Deploy a JavaScript/Rust app using [Turso embedded replicas](/features/embedded-replicas) to [Railway](https://railway.app/).

![Koyeb banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/railway-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   [Install the Railway CLI](https://docs.railway.app/guides/cli#installing-the-cli)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Get application code">
    Fork and clone the following embedded replica project from GitHub locally:

    <CardGroup cols={2}>
      <Card title="My Expenses Tracker - (Elysia + Bun)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-js">
        See the full source code
      </Card>

      <Card title="Web Traffic API - (Rust)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-rust">
        See the full source code
      </Card>
    </CardGroup>
  </Step>

  <Step title="Create a new Railway project">
    Run the following command to create a new Railway project. Provide the project's name when prompted.

    ```sh
    railway init
    ```
  </Step>

  <Step title="Add a service to the Railway project">
    [Create a new empty service](https://docs.railway.app/guides/services#creating-a-service) on your Railway project to act as your app's deployment target.
  </Step>

  <Step title="Link application to service">
    Run the following command to list and select the service to link to your application:

    ```sh
    railway service
    ```
  </Step>

  <Step title="Add database credentials">
    Open the service on your Railway dashboard and add your Turso database Credentials.

    ```sh
    TURSO_DATABASE_URL=libsql://[db-name]-[github-username].turso.io
    TURSO_AUTH_TOKEN=...
    LOCAL_DB=file:local-db-name.db
    ```
  </Step>

  <Step title="Deploy">
    Run the following command to deploy your application:

    ```sh
    railway up
    ```

    <Info>
      Make sure you [expose your application to the internet](https://docs.railway.app/guides/public-networking) to make it accessible from the public network.
    </Info>

    <Warning>
      If you are on a free plan, you'll need to connect your Railway account to GitHub to have access to code deployments.
    </Warning>
  </Step>
</Steps>


# Turso + Render

Deploy a JavaScript app using [Turso embedded replicas](/features/embedded-replicas) to [Render](https://render.com/).

![Render banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/render-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Render account - [create one](https://dashboard.render.com/)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Get application code">
    Fork the following embedded replica project from GitHub locally:

    <Card title="My Expenses Tracker - (Elysia + Bun)" icon="github" href="https://github.com/tursodatabase/embedded-replicas-with-js">
      See the full source code
    </Card>

    <Note>
      Or, you can:

      <Card title="Deploy to Render with a single-click" href="https://render.com/deploy?repo=https://github.com/tursodatabase/embedded-replicas-with-js" />
    </Note>
  </Step>

  <Step title="Create a web service">
    Create a new Render **Web Service** by clicking on the "New Web Service" button on the Web Services card inside you Render dashboard.
  </Step>

  <Step title="Connect to Git repository">
    1.  Select "build and deploy from a Git repository" and proceed to the next page.

    2.  Click on "Connect" for your target project repository
  </Step>

  <Step title="Set project's environment variables">
    On the web service configuration page, under "Advanced" add **a secret file** and fill it in with your database secret credentials:

    ![Render secret credentials](https://mintlify.s3-us-west-1.amazonaws.com/turso/features/embedded-replicas/images/platforms/render-env-vars.png)
  </Step>

  <Step title="Deploy project">
    Scroll to the bottom of the web service configuration page and click on "Create Web Service".
  </Step>
</Steps>


# Multi-DB Schemas

Create and share a single schema across multiple databases.

Turso allows you to create a single schema and share it across multiple databases. This is useful for creating a multi-tenant application where each tenant has their own database.

<Warning>
  This feature is currently in beta. [Join us in Discord](https://discord.gg/turso) to provide feedback and report any issues.
</Warning>

<Info>
  Try the [Turso Per User Starter](https://github.com/notrab/turso-per-user-starter) to get started with a multi-tenant application using Next.js, Drizzle, Clerk, libSQL, and Turso Multi-DB Schemas.
</Info>

## How it works

1.  You create a database that is used as the parent schema database.
2.  You create one or more databases that are used as the child databases.
3.  You apply schema changes to the parent database, child databases are automatically updated with the new schema.

## Usage

You can create and manage parent or child databases using the [Turso CLI](/cli/db/create), and [Platform API](/api-reference/databases/create).

<iframe src="https://www.youtube.com/embed/Slacu1aGm8A" title="Multi database schema changes" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen className="w-full aspect-video" />

### Turso CLI

Make sure you have the [Turso CLI](/cli/installation) installed, and [logged in](/cli/auth/login).

<Steps>
  <Step title="Create Parent Database">
    Create a single database using the `--type` flag set to `schema`:

    ```bash
    turso db create parent-db --type schema
    ```
  </Step>

  <Step title="Create Schema">
    Connect to your database using the shell to `CREATE TABLE`, `CREATE TRIGGER`, `CREATE VIEW`, and anything else to setup your schema:

    ```bash
    turso db shell parent-db
    ```
  </Step>

  <Step title="Create Child Database(s)">
    Create one or more child databases using the `--schema` flag with the name of the parent database:

    ```bash
    turso db create child-db --schema parent-db
    ```
  </Step>

  <Step title="Apply Additional Schema Changes">
    You can now apply additional schema changes to the parent database, and the child databases will be automatically updated:

    ```bash
    turso db shell parent-db "CREATE TABLE users (id INT PRIMARY KEY, name TEXT);"
    ```
  </Step>
</Steps>

### Platform API

Make sure you have an API Token, and know your Organization name:

<Steps>
  <Step title="Create Parent Database">
    Create a database and set the `is_schema` field to `true`:

    ```bash
    curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
      -H 'Authorization: Bearer TOKEN' \
      -H 'Content-Type: application/json' \
      -d '{
          "name": "parent-db",
          "group": "default",
          "is_schema": true
      }'
    ```
  </Step>

  <Step title="Create Schema">
    Connect to your database using the shell, [SDK](/sdk), or migration script to `CREATE TABLE`, `CREATE TRIGGER`, `CREATE VIEW`, and anything else to setup your schema:

    ```bash Turso CLI
    turso db shell parent-db
    ```
  </Step>

  <Step title="Create Child Database(s)">
    Create one or more child databases and pass the `schema` field the name of your parent database:

    ```bash
    curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
      -H 'Authorization: Bearer TOKEN' \
      -H 'Content-Type: application/json' \
      -d '{
          "name": "child-db",
          "group": "default",
          "schema": "parent-db"
      }'
    ```
  </Step>

  <Step title="Apply Additional Schema Changes">
    You can now apply additional schema changes to the parent database, and the child databases will be automatically updated:

    ```bash
    turso db shell parent-db "CREATE TABLE users (id INT PRIMARY KEY, name TEXT);"
    ```
  </Step>
</Steps>

## Things to know

*   Schema databases cannot be shared across groups or globally via an organization/account.
*   You can (but not recommended) `INSERT` rows into the parent database that can be queried by the child database(s).
    *   Be aware of any constraints that may conflict with the child database(s).
*   You can't delete a parent database if it has one or more child databases.
*   When a migration is applied to the schema database:
    *   It's first run as a dry-run on the schema and all other associated databases.
    *   If successful, a migration job is created.
    *   Tasks are created for each database that references this schema.
    *   The migration is then applied to each referencing database.
    *   Finally, if all tasks succeed, the migration is applied to the schema database itself.
    *   You can't create or delete a database if there are any migrations running.
*   **During a migration, all databases are locked to write operations.**
*   Make sure any application querying the child databases handle any databases not yet updated with the schema.
*   You cannot apply schema changes to a child database directly. You must use the parent (schema) database.


# Platform API

Manage databases, replicas, and teams with the Turso Platform API.

The Turso [Platform API](/api-reference) is a RESTful API that allows you to manage databases, replicas, and users. It is the same API that is used by the Turso Platform Web UI and [CLI](/cli).

The API is built for platforms that want to integrate with Turso to provide their users a globally distributed database, without managing database infrastructure and replication.

You can create databases, [database branches](/features/branching), [recover databases](/features/point-in-time-recovery) from a point in time, as well as [manage teams](/features/organizations), API tokens, and more with the Turso Platform API.

## API Resources

<Snippet file="platform-api-links.mdx" />


# Point-in-Time Recovery



Turso supports point-in-time recovery (PITR) for databases. PITR allows you to restore a database to a specific point in time. This is useful for recovering from user errors, such as dropping a table by mistake.

<Info>
  Backups are created automatically at `COMMIT`. Free plan users can restore to any point in time within the last 24 hours. Hobby, Scaler, and Pro users can restore to any point in time within the last 10, 30, or 90 days, respectively.
</Info>

## How it works

1.  You create a new database from the existing database using the CLI or API.
2.  You update your application to use the new database connection string.
3.  You delete the old database when you no longer need it.

<Info>
  The newly created database includes data only from periods prior to the specified timestamp. Additionally, there may be a gap of up to 15 seconds in the data immediately preceding the timestamp, as this depends on the timing of Turso's most recent periodic batch checkpoint.
</Info>

## Usage

<CodeGroup>
  ```bash CLI
  turso db create my-new-database --from-db my-existing-database --timestamp 2024-01-01T00:00:00Z
  ```

  ```bash Platform API
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "name": "new-database",
        "group": "default",
        "seed": {
          "type:": "database",
          "name": "my-existing-database",
          "timestamp": "2024-01-01T00:00:00Z"
        }
    }'
  ```
</CodeGroup>

Refer to the following references for more details about all arguments:

<CardGroup>
  <Card horizontal title="CLI Reference" icon="terminal" href="/cli/db/create" />

  <Card horizontal title="API Reference" icon="code" href="/api-reference/databases/create" />
</CardGroup>

## Things to know

*   Restoring from a PITR creates a new database. You will need to update your application to use the new database connection string.
*   You cannot restore from a PITR to a database that already exists.
*   You will need to [create a new token](/cli/db/tokens/create) (or use a group token) to connect to the new database.
*   You will need to manually delete the old database when you no longer need it.
*   Restores count towards your plan's database quota.


# Scale to Zero



For free Starter Plan users, Turso dynamically scales databases down to zero after an hour of no activity. This behaviour is how we can continue to provide hundreds of databases on the free plan.

When a request is made, the databases automatically scale back up to one. There may be a delay of up to `500ms` for databases that have been inactive.

<Info>
  [Database groups](/concepts#groups) with extended inactivity (**10 days**) will require a manual "unarchive" operation using the [CLI](/cli/group/unarchive) or API.
</Info>


# Usage & Billing



For the Starter and Scaler plans, Turso usage is limited monthly based on the following usage observations during each calendar month:

*   Number of table [rows read](#rows-read)
*   Number of table [rows written](#rows-written)
*   Amount of [total storage](#total-storage)

<Info>
  In billing plans that include monthly quotas for row reads, row writes, and total storage, any query that exceeds these limits will result in a failure, indicated by the `BLOCKED` error code.
</Info>

## Rows Read

In SQLite, the term "row read" actually refers to a "row scan" during statement execution. Key points to remember with the Turso CLI metrics:

*   **SQL Queries:** May scan more rows than returned.
*   **SQL Updates:** Each updated row results in at least one row scan.

### Aggregate Function Impact

Using functions like `count`, `avg`, `min`, `max`, and `sum` results in a row scan for every row considered in the aggregation.

<Info>
  Improve query efficiency by storing aggregate values in a separate table and
  updating it transactionally with the base table changes.
</Info>

### Full Table Scans

Queries lacking index support perform a full table scan, incurring a row scan for each table row.

<Info>
  Seek strategies to minimize costly table scans.
</Info>

### Complex Query Costs

Table joins, subqueries, and compound queries incur a row scan for each considered row from all involved tables.

### Update Mechanics

SQL updates read (and write) each row they modify. Absent an index for row filtering, a full table scan is performed, adding a read for each table row, plus a write for each updated row.

### `ALTER TABLE` and Row Reads

`ALTER TABLE` operations, especially those rewriting row contents, necessitate a full table scan, incurring a read for each table row. However, not all `ALTER TABLE` actions, like `DROP COLUMN`, lead to full scans. Be mindful of potential row writes as well.

### Indexing Costs

Adding an index to an existing table triggers a full table scan, with one read per existing row.

### SQLite System Tables

Internal SQLite tables, like `dbstat` and those with `sqlite_` prefix, don't incur row reads in queries.

### Zero-Read Commands

Commands not involving row reads/writes, like `select 1`, default to one row read.

## Rows Written

In SQLite, a "row written" encompasses both the insertion of a new row and the update of an existing row.

### `ALTER TABLE` and Row Writes

`ALTER TABLE` operations can result in a row write for each existing row, especially if the row data is altered during the process. It's important to understand how different types of `ALTER TABLE` statements impact row writes.

### Implications of Aborted Transactions

Even if a transaction is not committed, any row that was inserted or updated during the transaction incurs a row write. This underscores the importance of transaction management in controlling database writes.

<Note>
  `ALTER TABLE` actions may also lead to row reads, adding another layer to consider when modifying table structures.
</Note>

## Total Storage

SQLite utilizes the virtual table [`dbstat`](https://www.sqlite.org/dbstat.html) to calculate the total space used by all tables and indexes. The base unit for this measurement is a database file page, which is 4KB.

<Note>
  In SQLite, the `VACUUM` command is a common tool for optimizing storage by compacting the database. However, it's important to note that this command is currently disabled in Turso. Future updates may introduce options for developers to efficiently manage and reduce the total storage footprint of their databases.
</Note>

## Reducing Usage

### Query Execution

Familiarizing yourself with the [SQLite query planner](https://www.sqlite.org/queryplanner.html) can significantly enhance your understanding of how your queries are executed. This knowledge is pivotal in optimizing query efficiency.

### Query Planning

Utilize the [`EXPLAIN QUERY PLAN`](https://www.sqlite.org/eqp.html) statement to gain insights into your query's execution plan. This tool is invaluable for identifying whether your query is performing a full table scan and if it's leveraging the most efficient index to reduce unnecessary reads.

### Indexing

Ensure that your queries are designed to take advantage of indexes for row filtering. The absence of suitable indexes forces SQLite to resort to full table scans, incrementally increasing the read count by one for each row in the table. Efficient indexing is key to minimizing this overhead.

Incorporating necessary indexes at the table creation stage is a best practice. Adding indexes to tables that already contain rows triggers a full table scan, with each existing row necessitating one read. Proactive index management is crucial for maintaining optimal database performance.


# Welcome to Turso

SQLite for Production. Powered by libSQL.

<Frame>
  ![Turso Quickstart](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/turso-banner.png)
</Frame>

## New to Turso?

Turso is a SQLite-compatible database built on [libSQL](/libsql), the Open Contribution fork of SQLite.

<CardGroup cols={2}>
  <Card
    title="Get Started"
    icon={
     <svg
       width="25"
       viewBox="0 0 48 43"
       fill="none"
       xmlns="http://www.w3.org/2000/svg"
     >
       <g clip-path="url(#clip0_172_7499)">
         <path
           d="M32.32 20.36L32.82 27.08L33.01 29.59L30.57 30.21C29.06 30.59 26.99 31.12 24 31.12C21.01 31.12 18.94 30.59 17.43 30.21L14.99 29.59L15.18 27.08L15.68 20.36L7.79999 17.62C8.26999 22.97 10.11 33.84 10.66 34.9C11.3 36.12 14.69 39.62 17.34 40.96C17.34 40.96 18.3 39.94 18.89 39.04C19.63 39.92 23.48 43.01 24 43.01C24.52 43.01 28.37 39.92 29.11 39.04C29.7 39.94 30.66 40.96 30.66 40.96C33.31 39.62 36.7 36.12 37.34 34.9C37.89 33.84 39.73 22.97 40.2 17.62L32.32 20.36Z"
           fill="#1EBCA1"
         />
         <path
           d="M29.15 18.28L48 11.73C46.88 4.99 41 0.01 41 0.01V7.42L37.51 8.32L35.32 5.67L33.45 9.37L24 11.82L14.55 9.37L12.68 5.67L10.49 8.32L7 7.42V0C7 0 1.12 4.99 0 11.72L18.85 18.27L18.18 27.29C19.79 27.7 21.48 28.11 24.01 28.11C26.54 28.11 28.23 27.7 29.84 27.29L29.17 18.27L29.15 18.28Z"
           fill="#1EBCA1"
         />
       </g>
       <defs>
         <clipPath id="clip0_172_7499">
           <rect width="48" height="43" fill="white" />
         </clipPath>
       </defs>
     </svg>
    }
    href="/quickstart"
  >
    Create your first database
  </Card>

  <Card
    title="Embedded Replicas"
    icon={
     <svg viewBox="0 0 216 216" xmlns="http://www.w3.org/2000/svg">
       <path
         d="m25.3 114.3 15.9 48c1.5 4.5 5 8 9.5 9.5l48 15.9c5.3 1.8 11.2.4 15.2-3.6l76.7-76.7c3-3 4.6-7.1 4.3-11.4l-3.7-64c-.3-5.5-4.7-10-10.3-10.3l-64-3.7c-4.2-.2-8.4 1.3-11.4 4.3l-76.6 76.8c-4 4-5.4 9.9-3.6 15.2z"
         fill="none"
         stroke="#1ebca1"
         stroke-miterlimit="10"
         stroke-width="19.2"
       />
       <path
         d="m119.2 82.2 6.5-1.5c2.9-.7 5.8 1.2 6.5 4.1.2.8.2 1.6 0 2.4l-1.5 6.5c-3.3 12.4-21.1 8.4-18.8-4.2.8-3.8 3.8-6.5 7.3-7.3z"
         fill="#1ebca1"
       />
       <path
         d="m21.1 191.8 99.8-99.8"
         fill="none"
         stroke="#1ebca1"
         stroke-linecap="round"
         stroke-linejoin="round"
         stroke-width="19.2"
       />
       <g fill="#1ebca1">
         <path d="m141.8 142.4c-1.4 1.4-3.5 1.9-5.4 1.3l-13.3-4.4c-2-.7-4.3-.1-5.8 1.4l-8.9 8.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
         <path d="m107 177.2c-1.4 1.4-3.5 1.9-5.4 1.3l-14.6-4.8c-1.2-.4-2.5 0-3.4.8l-9.9 9.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
         <path d="m175.2 109c-1.4 1.4-3.5 1.9-5.4 1.3l-13.3-4.4c-2-.7-4.3-.1-5.8 1.4l-8.9 8.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
       </g>
     </svg>
    }
    href="/features/embedded-replicas/introduction"
  >
    Get zero latency reads on-device
  </Card>

  <Card
    title="AI & Embeddings"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#1ebca1">
       <path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z" />
     </svg>
    }
    href="/features/ai-and-embeddings"
  >
    Vector is just another datatype
  </Card>

  <Card title="Multi-DB Schemas" icon="boxes-stacked" href="/features/multi-db-schemas">
    Share schema across multiple databases
  </Card>

  <Card icon="globe" title="Edge Replicas" href="/features/data-edge">
    Get low latency with edge replicas
  </Card>

  <Card
    icon={
     <svg
       xmlns="http://www.w3.org/2000/svg"
       fill="none"
       viewBox="0 0 24 24"
       stroke-width="1.5"
       stroke="#1ebca1"
     >
       <path
         stroke-linecap="round"
         stroke-linejoin="round"
         d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3"
       />
     </svg>
    }
    title="Backups and Recovery"
    href="/features/point-in-time-recovery"
  >
    Restore your database to any point in time
  </Card>
</CardGroup>

## Start building

Learn how to manage, distribute and integrate your databases with the CLI, API and SDKs.

<CardGroup cols={2}>
  <Card title="Turso CLI" icon="terminal" href="/cli">
    Manage groups, databases, and API tokens with the Turso CLI.
  </Card>

  <Card title="Turso Platform API" icon="database" href="/api-reference">
    Manage groups, databases, and API tokens with the Turso API.
  </Card>

  <Card
    title="Client SDKs"
    icon={
     <svg viewBox="0 0 216 216" xmlns="http://www.w3.org/2000/svg">
       <path
         d="m25.3 114.3 15.9 48c1.5 4.5 5 8 9.5 9.5l48 15.9c5.3 1.8 11.2.4 15.2-3.6l76.7-76.7c3-3 4.6-7.1 4.3-11.4l-3.7-64c-.3-5.5-4.7-10-10.3-10.3l-64-3.7c-4.2-.2-8.4 1.3-11.4 4.3l-76.6 76.8c-4 4-5.4 9.9-3.6 15.2z"
         fill="none"
         stroke="#1ebca1"
         stroke-miterlimit="10"
         stroke-width="19.2"
       />
       <path
         d="m119.2 82.2 6.5-1.5c2.9-.7 5.8 1.2 6.5 4.1.2.8.2 1.6 0 2.4l-1.5 6.5c-3.3 12.4-21.1 8.4-18.8-4.2.8-3.8 3.8-6.5 7.3-7.3z"
         fill="#1ebca1"
       />
       <path
         d="m21.1 191.8 99.8-99.8"
         fill="none"
         stroke="#1ebca1"
         stroke-linecap="round"
         stroke-linejoin="round"
         stroke-width="19.2"
       />
       <g fill="#1ebca1">
         <path d="m141.8 142.4c-1.4 1.4-3.5 1.9-5.4 1.3l-13.3-4.4c-2-.7-4.3-.1-5.8 1.4l-8.9 8.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
         <path d="m107 177.2c-1.4 1.4-3.5 1.9-5.4 1.3l-14.6-4.8c-1.2-.4-2.5 0-3.4.8l-9.9 9.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
         <path d="m175.2 109c-1.4 1.4-3.5 1.9-5.4 1.3l-13.3-4.4c-2-.7-4.3-.1-5.8 1.4l-8.9 8.9c-1.8 1.8-1.1 4.8 1.3 5.6l20.6 6.8c8.9 2.9 18.4.6 25-5.9" />
       </g>
     </svg>
    }
    href="/sdk"
  >
    Connect and integrate Turso into your application with one of our libSQL
    drivers.
  </Card>

  <Card title="Tutorials" icon="newspaper" href="https://turso.tech/blog">
    Learn how to work with Turso and your favorite language or framework.
  </Card>
</CardGroup>

## Join the community

Join the Turso community to ask questions, discuss best practices, and share tips.

<CardGroup cols={3}>
  <Card title="Discord" icon="discord" href="https://discord.gg/turso" />

  <Card title="GitHub" icon="star" href="https://github.com/tursodatabase" />

  <Card title="X (Twitter)" icon="x-twitter" href="https://twitter.com/tursodatabase" />
</CardGroup>


# libSQL

libSQL is SQLite for modern applications.

Turso is a distributed database built on [libSQL](https://github.com/tursodatabase/libsql/), a fork of SQLite. It's optimized for low query latency, making it suitable for global applications.

Postgres and MySQL have long vied for SQL dominance, while SQLite remains a favored choice due to its simplicity and reliability, often dubbed the "hello world" of databases.

libSQL is a fork of SQLite that aims to be a modern database, with a focus on low query latency and high availability. It's designed to be a drop-in replacement for SQLite, and scales globally with Turso over HTTP.

<CardGroup cols={2}>
  <Card title="tursodatabase/libsql" icon="github" href="https://github.com/tursodatabase/libsql/">
    Browse the libSQL source code on GitHub, report issues, feature requests and contribute using pull requests.
  </Card>

  <Card title="Discord" href="https://discord.gg/turso" icon="discord">
    Join the community on Discord to talk about the development of libSQL.
  </Card>
</CardGroup>

## Why fork SQLite?

SQLite is [open-source, not open-contribution](https://www.sqlite.org/copyright.html), which makes it difficult to innovate and evolve with it.

Turso is committed to the open-source community, and we welcome contributions to libSQL. We're also committed to keeping libSQL free and open-source, as well rejoining core SQLite if their policy changes.

Read the [libSQL Manifesto](https://turso.tech/libsql-manifesto) for more details.

## Turso vs. libSQL

Turso manages the distribution of libSQL instances, and provides a global HTTP API for querying and managing databases. It also provides a CLI, Web UI and HTTP API for managing databases, replicas using groups, and team management.

When you use Turso, you don't need to worry about managing libSQL instances, or configuring replication. You can focus on building your application, and let Turso handle the rest.

[SDKs](/sdk) are fully compatible with libSQL, whether you use self-hosted or Turso-hosted libSQL.

## SQLite Compatibility

libSQL will remain SQLite compatible by providing the same API and file format, but with additional features and optimizations.

## Encryption at rest

libSQL introduces an essential feature for production environments: **encryption at rest**. This feature enhances data security by encrypting database files, making them inaccessible without the correct encryption key.

libSQL's encryption leverages existing, proven encryption solutions, integrating them directly into the fork of SQLite. The encryption is page-based, allowing for efficient data access without decrypting the entire file. Supported encryption standards include SQLCipher (default) and wxSQLite3's AES 256 Bit, with further options for customization per database.

<CodeGroup>
  <Snippet file="encryption-at-rest-typescript.mdx" />

  <Snippet file="encryption-at-rest-golang.mdx" />

  <Snippet file="encryption-at-rest-rust.mdx" />

  <Snippet file="encryption-at-rest-python.mdx" />

  <Snippet file="encryption-at-rest-flutter.mdx" />
</CodeGroup>

<Note>The encryption key used should be generated and managed by you.</Note>

## Extensions

<Warning>
  Extensions are experimental. [Join us on Discord](https://discord.gg/turso) to add your suggestions and feedback.
</Warning>

<Info>
  If you're looking to enable vector extensions, you should instead consider
  using the native [libSQL vector datatype](/features/ai-and-embeddings).
</Info>

| Extension                                                                     | Version  | Installed | Description                                                                 |
| ----------------------------------------------------------------------------- | -------- | --------- | --------------------------------------------------------------------------- |
| [JSON](https://www.sqlite.org/json1.html)                                     | Built-in | Default   | Work with JSON data in SQLite.                                              |
| [FTS5](https://www.sqlite.org/fts5.html)                                      | Built-in | Default   | Full-text search and indexing.                                              |
| [R\*Tree](https://www.sqlite.org/rtree.html)                                  | Built-in | Default   | Indexing and querying spatial data.                                         |
| [sqlite-vec](https://github.com/asg017/sqlite-vec/tree/v0.1.1)                | 0.1.0    | Opt-in    | The Vector Search successor to `sqlite-vss`.                                |
| [SQLean Crypto](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/crypto.md) | 0.24.1   | Opt-in    | Hashing, message digest, encoding, and decoding.                            |
| [SQLean Fuzzy](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/fuzzy.md)   | 0.24.1   | Opt-in    | Fuzzy string matching and phonetics. A fork of Spellfix1 with improvements. |
| [SQLean Math](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/math.md)     | 0.24.1   | Opt-in    | Advanced mathematical calculations.                                         |
| [SQLean Regexp](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/regexp.md) | 0.24.1   | Opt-in    | Regular expressions with SQLite.                                            |
| [SQLean Stats](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/stats.md)   | 0.24.1   | Opt-in    | Common statistical functions with SQLite.                                   |
| [SQLean Text](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/text.md)     | 0.24.1   | Opt-in    | String manipulation (reverse, split) with SQLite.                           |
| [SQLean UUID](https://github.com/nalgeon/sqlean/blob/0.24.1/docs/uuid.md)     | 0.24.1   | Opt-in    | Limited support for RFC 4122 compliant UUIDs.                               |

You can enable all extensions when creating a new database using the [CLI](/cli/db/create) or [API](/api-reference/databases/create):

<CodeGroup>
  ```bash Turso CLI
  turso db create [database-name] --enable-extensions
  ```

  ```bash Platform API
  curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases' \
    -H 'Authorization: Bearer TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
        "name": "new-database",
        "group": "default",
        "extensions": "all"
    }'
  ```
</CodeGroup>

If you already have a group created with extensions disabled, you can update all databases in a group to enable extensions:

```bash
turso group update <group-name> --extensions all
```


# Local Development

Build locally using SQLite, libSQL Server or Turso.

Developers can build locally with Turso using either of the following methods:

*   [SQLite](#sqlite) — local SQLite database file
*   [Turso CLI](#turso-cli) — managed libSQL server
*   [libSQL Server](#libsql-server) — self managed libSQL server
*   [Turso Database](#turso-database) — remote Turso database

## Using a dump locally

You can always dump your production database and use it locally for development:

<Steps>
  <Step title="Create a dump using the Turso CLI">
    ```bash
    turso db shell your-database .dump > dump.sql
    ```
  </Step>

  <Step title="Create SQLite file from dump">
    ```bash
    cat dump.sql | sqlite3 local.db
    ```
  </Step>

  <Step title="Connect to SQLite file">
    You can use any of the methods below with the `local.db` file, or you can use a new file name if you prefer to create a database from scratch.
  </Step>
</Steps>

## SQLite

There are a few things to keep in mind when using SQLite for local development:

*   Doesn't have all the features of libSQL
*   Works with non-serverless based Turso SDKs

When working with an [SDK](/sdk), you can pass it a `file:` URL to connect to a SQLite database file instead of a remote Turso database:

<CodeGroup>
  ```ts JavaScript
  import { createClient } from "@libsql/client";

  const client = createClient({
    url: "file:local.db",
  });
  ```

  ```rust Rust
  let client = libsql_client::Client::from_config(libsql_client::Config {
      url: url::Url::parse("file:local.db").unwrap(),
      auth_token: None,
  })
  .await
  .unwrap();
  ```

  ```go Go
  package main

  import (
    "database/sql"
    "fmt"
    "os"

    _ "github.com/tursodatabase/go-libsql"
  )

  func main() {
    dbName := "file:./local.db"

    db, err := sql.Open("libsql", dbName)
    if err != nil {
      fmt.Fprintf(os.Stderr, "failed to open db %s", err)
      os.Exit(1)
    }
    defer db.Close()
  }
  ```

  ```python Python
  import libsql_client

  client = libsql_client.create_client_sync(
      url="file:local.db"
  )
  ```
</CodeGroup>

<br />

<Info>
  You don't need to provide an `authToken` in development.
</Info>

<Info>
  It's recommended to use environment variables for both `url` and `authToken` for a seamless developer experience.
</Info>

## Turso CLI

If you're using [libSQL](/libsql) specific features like [extensions](/libsql#extensions), you should use the Turso CLI:

```bash
turso dev
```

This will start a local libSQL server and create a database for you. You can then connect to it using the `url` option in your SDK:

<CodeGroup>
  ```ts JavaScript
  import { createClient } from "@libsql/client";

  const client = createClient({
    url: "http://127.0.0.1:8080",
  });
  ```

  ```rust Rust
  let client = libsql_client::Client::from_config(libsql_client::Config {
      url: url::Url::parse("http://127.0.0.1:8080").unwrap(),
      auth_token: None,
  })
  .await
  .unwrap();
  ```

  ```python Python
  import libsql_client

  client = libsql_client.create_client_sync(
      url="http://127.0.0.1:8080"
  )
  ```
</CodeGroup>

<br />

<Warning>
  Changes will be lost when you stop the server.
</Warning>

If you want to persist changes, or use a production dump, you can pass the `--db-file` flag with the name of the SQLite file:

```bash
turso dev --db-file local.db
```

## libSQL Server

You can build and run libSQL server (`sqld`) yourself locally, or inside your own infrastructure using the source code:

<CardGroup cols={2}>
  <Card title="tursodatabase/libsql" icon="github" href="https://github.com/tursodatabase/libsql" />
</CardGroup>

## Turso Database

If you already have a database created with Turso, you can use that same one in development by passing the `url` option to your SDK.

<Warning>
  Keep in mind that using the Turso hosted database will incur platform costs and count towards your quota. Consider using [SQLite](#sqlite) or [Turso CLI](#turso-cli) for local development to avoid platform costs.
</Warning>

## Connecting a GUI

During development you can easily connect to a SQLite, libSQL, or Turso database using one of the tools below:

*   [Beekeeper Studio](https://www.beekeeperstudio.io/db/libsql-client/) — macOS, Linux, and Windows
*   [Outerbase](https://www.outerbase.com) — Runs in the browser
*   [TablePlus](https://tableplus.com) — macOS, Windows, and Linux
*   [Dataflare](https://dataflare.app) — Paid (with limited free version) macOS, Windows, and Linux
*   [libSQL Studio](https://github.com/invisal/libsql-studio) - Runs in the browser
*   [DBeaver](https://dbeaver.io) - macOS, Windows, and Linux


# Quickstart

Welcome to Turso! Get started with Turso in minutes.

**In this quickstart you will learn how to:**

1.  Install the Turso CLI
2.  Signup to Turso
3.  Create your first Turso Database
4.  Connect to Database Shell
5.  Replicate Database to another region

<Steps>
  <Step title="Install the Turso CLI">
    We'll be using the Turso CLI throughout this quickstart to manage databases, create replicas in other regions, and connect to the database shell.

    <CodeGroup>
      ```bash macOS
      brew install tursodatabase/tap/turso
      ```

      ```bash Linux
      curl -sSfL https://get.tur.so/install.sh | bash
      ```

      ```bash Windows
      curl -sSfL https://get.tur.so/install.sh | bash
      ```
    </CodeGroup>
  </Step>

  <Step title="Signup to Turso">
    The next command will open your browser to sign up:

    <CodeGroup>
      ```bash Signup
      turso auth signup
      ```

      ```bash Login
      turso auth login
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a Database">
    Now create your first database in a location closest to you with the name `my-db`:

    ```bash
    turso db create my-db
    ```

    The Turso CLI automatically detected your closest region to create a database. It used this location to create a `default` "group" for your database, which you can inspect using the following command:

    ```bash
    turso db show my-db
    ```
  </Step>

  <Step title="Connect to Database Shell">
    Congratulations, you created a database! Now connect to it with the `shell` command:

    ```bash
    turso db shell my-db
    ```

    <Info>
      Replace `my-db` with the name of your database if you named it differently.
    </Info>

    <AccordionGroup>
      <Accordion title="Create table">
        Now create a table for `users` using SQL:

        ```sql
        CREATE TABLE users (
          ID INTEGER PRIMARY KEY AUTOINCREMENT,
          name TEXT
        );
        ```
      </Accordion>

      <Accordion title="Insert into new table">
        Then insert a row into the `users` table:

        ```sql
        INSERT INTO users (name) VALUES ("Iku");
        ```
      </Accordion>

      <Accordion title="Select all rows from table">
        Finally, query for all `users`:

        ```sql
        SELECT * FROM users;
        ```
      </Accordion>
    </AccordionGroup>

    When you're ready to move onto the next step, you'll want to to quit the shell:

    ```sql
    .quit
    ```
  </Step>

  <Step title="Replicate Database to another region">
    Adding a database replica is an easy as adding another location to the "group" your database belongs to.

    First, you can fetch a list of supported locations using the Turso CLI:

    ```bash
    turso db locations
    ```

    Pick a location for your database to replicate it to and pass the three-digit code to the `groups locations add` command:

    ```bash
    turso group locations add default nrt
    ```

    **Congratulations**! Your data is now replicated and closer to users in two regions.
  </Step>

  <Step title="Connect your application to your database">
    You're now ready to connect your application to your database. Pick from one of the SDKs below to continue:

    <Snippet file="all-sdks.mdx" />
  </Step>
</Steps>


# Authentication



SDKs connect to Turso using the `libsql://` protocol, unless using the [HTTP API](/sdk/http).

## Database URL

You can find your database URL using the [Turso CLI](/cli/db/show) or [Platform API](/api-reference/databases/retrieve), it looks something like this:

<CodeGroup>
  ```bash libSQL
  libsql://[DB-NAME]-[ORG-NAME].turso.io
  ```

  ```bash HTTPS
  https://[DB-NAME]-[ORG-NAME].turso.io
  ```
</CodeGroup>

<br />

<Info>
  WebSockets generally offer better performance when maintaining an open socket for multiple queries, whereas HTTP is typically more efficient for single queries due to reduced client-server round trips — it's advisable to benchmark both to ascertain the best option for your specific needs.
</Info>

## Auth Tokens

SDKs require an auth token, unless [working locally](/local-development). You can create a new token for your database (or group) using the [Turso CLI](/cli) and [Platform API](/api-reference).

Using Turso CLI and Platform API you can:

*   Create tokens for a one database or all databases in a group
*   Create `full-access` and `read-only` tokens
*   Set expiration for tokens
*   Invalidate all tokens


# Turso Examples (C)



| Example                                                                                     | Description                                                                             |
| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| [local](https://github.com/tursodatabase/libsql-c/tree/master/examples/local)               | Uses libsql with a local SQLite file. Creates database, inserts data, and queries.      |
| [remote](https://github.com/tursodatabase/libsql-c/tree/master/examples/remote)             | Connects to a remote database. Requires environment variables for URL and auth token.   |
| [sync](https://github.com/tursodatabase/libsql-c/tree/master/examples/sync)                 | Demonstrates synchronization between local and remote databases.                        |
| [batch](https://github.com/tursodatabase/libsql-c/tree/master/examples/batch)               | Executes multiple SQL statements in a single batch operation.                           |
| [transactions](https://github.com/tursodatabase/libsql-c/tree/master/examples/transactions) | Shows transaction usage: starting, performing operations, and committing/rolling back.  |
| [memory](https://github.com/tursodatabase/libsql-c/tree/master/examples/memory)             | Uses an in-memory SQLite database for temporary storage or fast access.                 |
| [vector](https://github.com/tursodatabase/libsql-c/tree/master/examples/vector)             | Works with vector embeddings, storing and querying for similarity search.               |
| [encryption](https://github.com/tursodatabase/libsql-c/tree/master/examples/encryption)     | Creates and uses an encrypted SQLite database, demonstrating setup and data operations. |


# Turso Quickstart (C)

Get started with Turso and C using the libSQL client in a few simple steps.

<Snippet file="technical-preview-banner.mdx" />

In this C quickstart we will learn how to:

*   Retrieve database credentials
*   Install the libSQL package
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Snippet file="mobile-secrets-warning.mdx" />
  </Step>

  <Step title="Install">
    To use libSQL with C, you need to build the library from source:

    <Card title="libSQL C" href="https://github.com/tursodatabase/libsql">
      Build from source code
    </Card>

    After building, make sure to link against the library when compiling your C program:

    ```bash
    gcc -o your_program your_program.c -L/path/to/libsql/lib -llibsql
    ```
  </Step>

  <Step title="Connect">
    You must first initialize libSQL, create a `libsql_database_t` object, and then open a `libsql_connection_t` to it:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```c
        #include "libsql.h"

        libsql_setup((libsql_config_t){0});

        libsql_database_t db = libsql_database_init((libsql_database_desc_t){
            .path = "local.db",
            .url = "TURSO_DATABASE_URL",
            .auth_token = "TURSO_AUTH_TOKEN",
            .sync_interval = 300
        });

        libsql_connection_t conn = libsql_database_connect(db);
        ```
      </Accordion>

      <Accordion title="Local only">
        ```c
        #include "libsql.h"

        libsql_setup((libsql_config_t){0});

        libsql_database_t db = libsql_database_init((libsql_database_desc_t){
            .path = "local.db"
        });

        libsql_connection_t conn = libsql_database_connect(db);
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```c
        #include "libsql.h"

        libsql_setup((libsql_config_t){0});

        libsql_database_t db = libsql_database_init((libsql_database_desc_t){
            .url = "TURSO_DATABASE_URL",
            .auth_token = "TURSO_AUTH_TOKEN"
        });

        libsql_connection_t conn = libsql_database_connect(db);
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database by preparing a statement and then executing it:

    ```c
    libsql_statement_t stmt = libsql_connection_prepare(conn, "SELECT * FROM users");
    libsql_rows_t rows = libsql_statement_query(stmt);
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```c Positional Query
      libsql_statement_t stmt = libsql_connection_prepare(conn, "SELECT * FROM users WHERE id = ?");
      libsql_statement_bind_value(stmt, libsql_integer(1));
      libsql_rows_t rows = libsql_statement_query(stmt);
      ```

      ```c Positional Insert
      libsql_statement_t stmt = libsql_connection_prepare(conn, "INSERT INTO users (id) VALUES (?)");
      libsql_statement_bind_value(stmt, libsql_integer(1));
      libsql_execute_t result = libsql_statement_execute(stmt);
      ```
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas, you should call `libsql_database_sync()` on the database to sync your local database with the primary database, unless you are using `sync_interval` (though there is no issue with calling `sync` with `sync_interval` enabled):

    ```c
    libsql_sync_t sync = libsql_database_sync(db);
    if (sync.err) {
        fprintf(stderr, "Error syncing database: %s\n", libsql_error_message(sync.err));
    } else {
        printf("Sync completed. Frame number: %llu, Frames synced: %llu\n",
                (unsigned long long)sync.frame_no,
                (unsigned long long)sync.frames_synced);
    }
    ```
  </Step>
</Steps>


# C Reference

libSQL C Reference

<Snippet file="technical-preview-banner.mdx" />

## Installing

To use the libSQL C bindings, you need to include the `libsql.h` header file in your project and link against the `liblibsql.so` shared library.

<Card title="libSQL C" href="https://github.com/tursodatabase/libsql">
  Build from source code
</Card>

Before using libSQL, you need to call the setup function:

```c
libsql_setup((libsql_config_t){0});
```

## In-Memory Databases

libSQL supports connecting to \[in-memory
databases]\([https://www.sqlite.org/inmemorydb.htm](https://www.sqlite.org/inmemorydb.htm) databases for cases where you don't require persistence:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){.path = ":memory:"});
libsql_connection_t conn = libsql_database_connect(db);
```

## Local Development

You can work locally using an SQLite file:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){.path = "local.db"});
libsql_connection_t conn = libsql_database_connect(db);
```

## Remote Databases

You can connect to remote databases using a URL and auth token:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){
    .url = "TURSO_DATABASE_URL",
    .auth_token = "TURSO_AUTH_TOKEN"
});
libsql_connection_t conn = libsql_database_connect(db);
```

## Embedded Replicas

You can work with embedded replicas that can sync from the remote URL and delegate writes to the remote primary database:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){
    .path = "local.db",
    .url = "TURSO_DATABASE_URL",
    .auth_token = "TURSO_AUTH_TOKEN"
});
libsql_connection_t conn = libsql_database_connect(db);
```

### Manual Sync

The `libsql_database_sync` function allows you to sync manually the local database with the remote counterpart:

```c
libsql_sync_t sync = libsql_database_sync(db);
```

### Sync Interval

The `sync_interval` parameter in the database description allows you to set an interval for automatic synchronization of the database in the background:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){
    .path = "local.db",
    .url = "TURSO_DATABASE_URL",
    .auth_token = "TURSO_AUTH_TOKEN",
    .sync_interval = 60000
});
```

### Read Your Own Writes

The `not_read_your_writes` parameter in the database description configures the database connection to ensure that writes are immediately visible to subsequent read operations initiated by the same connection. This is **enabled by default**, and you can disable it by setting `not_read_your_writes` to `true`:

```c
libsql_database_t db = libsql_database_init((libsql_database_desc_t){
    .path = "local.db",
    .url = "TURSO_DATABASE_URL",
    .auth_token = "TURSO_AUTH_TOKEN",
    .not_read_your_writes = true
});
```

## Simple query

You can use `libsql_connection_batch` for simple queries without parameters:

```c
libsql_batch_t batch = libsql_connection_batch(conn, "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
```

For queries with results, use `libsql_connection_prepare` and `libsql_statement_query`:

```c
libsql_statement_t stmt = libsql_connection_prepare(conn, "SELECT * FROM users");
libsql_rows_t rows = libsql_statement_query(stmt);
```

## Prepared Statements

You can prepare a statement using `libsql_connection_prepare` and then execute it with `libsql_statement_execute` or `libsql_statement_query`:

```c
libsql_statement_t stmt = libsql_connection_prepare(conn, "INSERT INTO users (name) VALUES (?)");
libsql_statement_bind_value(stmt, libsql_text("John Doe", 8));
libsql_execute_t result = libsql_statement_execute(stmt);
```

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```c Positional
  libsql_statement_t stmt = libsql_connection_prepare(conn, "SELECT * FROM users WHERE id = ?");
  libsql_statement_bind_value(stmt, libsql_integer(1));
  ```

  ```c Named
  libsql_statement_t stmt = libsql_connection_prepare(conn, "SELECT * FROM users WHERE id = :id");
  libsql_statement_bind_named(stmt, ":id", libsql_integer(1));
  ```
</CodeGroup>

## Transactions

libSQL supports transactions:

```c
libsql_transaction_t tx = libsql_connection_transaction(conn);
// Perform operations within the transaction
libsql_transaction_commit(tx); // or libsql_transaction_rollback(tx)
```

## Cleanup

Remember to clean up resources when you're done:

```c
libsql_statement_deinit(stmt);
libsql_connection_deinit(conn);
libsql_database_deinit(db);
```


# Examples





# Drift + Turso / LibSQL

Configure `drift` to work with `libsql_dart`

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)

<Steps>
  <Step title="Add packages to your project">
    ```bash
    flutter pub add drift_libsql drift drift_flutter dev:build_runner dev:drift_dev
    ```
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Create a table schema">
    ```dart
    class TaskTable extends Table {
      IntColumn get id => integer().autoIncrement()();
      TextColumn get title => text()();
      TextColumn get description => text()();
      BoolColumn get completed => boolean()();
    }
    ```
  </Step>

  <Step title="Create db class">
    ```dart
    @DriftDatabase(tables: [TaskTable])
    class AppDatabase extends _$AppDatabase {
      AppDatabase(super.e);

      @override
      int get schemaVersion => 1;
    }
    ```
  </Step>

  <Step title="Run build runner">
    ```bash
    dart run build_runner build
    ```
  </Step>

  <Step title="Create the db">
    ```dart
    final db = AppDatabase(DriftLibsqlDatabase(
        "${dir.path}/replica.db",
        syncUrl: url,
        authToken: token,
        readYourWrites: true,
        syncIntervalSeconds: 3,
      ));
    ```
  </Step>

  <Step title="Perform SQL operations">
    ```dart
    await db.into(db.taskTable).insert(TaskTableCompanion.insert(
    	title: task.title,
    	description: task.description,
    	completed: task.completed));
    ```
  </Step>
</Steps>


# Turso Quickstart (Flutter / Dart)

Get started with Flutter and Dart using the libSQL client in a few simple steps

<Note>
  This SDK is community maintained and may not be officially supported by Turso, or up to date with the latest features. Join the `#libsql-dart` channel [on Discord](https://discord.gg/turso) for help and feedback.
</Note>

In this Flutter/Dart quickstart we will learn how to:

*   Retrieve database credentials
*   Install the Flutter/Dart libSQL client
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install libsql_dart">
    ```bash
    flutter pub add libsql_dart
    ```
  </Step>

  <Step title="Initialize">
    Now connect to your local or remote database using the `LibsqlClient` constructor:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```dart
        final dir = await getApplicationCacheDirectory();
        final path = '${dir.path}/local.db';

        final client = LibsqlClient(path)
          ..authToken = '<TOKEN>'
          ..syncUrl = '<TURSO_OR_LIBSQL_URL>'
          ..syncIntervalSeconds = 5
          ..readYourWrites = true;
        ```
      </Accordion>

      <Accordion title="Local only">
        <CodeGroup>
          ```dart File
          final dir = await getApplicationCacheDirectory();
          final path = '${dir.path}/local.db';

          final client = LibsqlClient(path);
          ```

          ```dart In-Memory
          final client = LibsqlClient(":memory:");
          ```
        </CodeGroup>
      </Accordion>

      <Accordion title="Remote only">
        ```dart
        final client = LibsqlClient('<TURSO_OR_LIBSQL_URL>')
          ..authToken = '<TOKEN>';
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Connect">
    ```dart
    await client.connect();
    ```
  </Step>

  <Step title="Execute">
    <CodeGroup>
      ```dart Execute
      await client.execute("create table if not exists customers (id integer primary key, name text);");
      ```

      ```dart Insert
      await client.query("insert into customers(name) values ('John Doe')");
      ```

      ```dart Select
      print(await client.query("select * from customers"));
      ```

      ```dart Batch
      await client.batch("""insert into customers (name) values ('Jane Doe'); insert into customers (name) values ('Jake Doe');""");
      ```

      ```dart Prepared statement
      final statement = await client
      	.prepare("select * from customers where id = ?");

      await statement.query(positional: [1])
      ```

      ```dart Interactive transaction
      final tx = await client.transaction();

      await tx
      	.execute("update customers set name = 'John Noe' where id = 1");
      await tx
      	.execute("update customers set name = 'Jane Noe' where id = 2");
      print(await tx
      	.query("select * from customers where id = ?", positional: [1]));

      await tx.commit();
      ```
    </CodeGroup>

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```dart Positional
      final statement = await client
        .prepare("select * from customers where id = ?");

      await statement.query(positional: [1])
      ```

      ```dart Named
      final statement = await client
      	.prepare("select * from customers where id = :id");

      await statement.query(named: {"id": 1})
      ```
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the connector to sync your local database with the primary database.

    ```dart
    await client.sync();
    ```
  </Step>
</Steps>


# Reference

libSQL Flutter / Dart Reference

The libSQL package for Flutter / Dart contains everything you need to work with Turso / libSQL and works flawlessly with all features, because it’s build on top libSQL Rust crate and `flutter_rust_bridge` package, allowing for seamless communication between Rust and Dart.

## Add the package to your project

```bash
flutter pub add libsql_dart
```

Alternatively, manually add it to your project's `pubspec.yaml`

```yaml
libsql_dart:
```

## Initializing

Call `LibsqlClient` constructor to create the database client. Different configurations are supported, allowing connection to in-memory database, local sqlite file, remote Turso / libSQL database, or embedded replica.

## In-Memory Databases

libSQL supports connecting to [in-memory databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't require persistence:

```dart
final client = LibsqlClient(":memory:");
```

## Local Development

You can work locally using an SQLite file and passing the path to `LibsqlClient`:

```dart
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';

final client = LibsqlClient(path);
```

## Remote

You can work with remote database by passing your Turso Database URL:

```dart
final client = LibsqlClient('<TURSO_OR_LIBSQL_URL>')
	..authToken = '<TOKEN>';
```

## Embedded Replicas

You can work with embedded replicas by passing your Turso Database URL to `syncUrl`:

```dart
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';

final client = LibsqlClient(path)
	..authToken = '<TOKEN>'
	..syncUrl = '<TURSO_OR_LIBSQL_URL>'
	..readYourWrites = true;
```

<Snippet file="embedded-replicas-warning.mdx" />

### Connect

```dart
await client.connect();
```

### Manual Sync

The `sync()` function allows you to sync manually the local database with the remote counterpart:

```ts
await client.sync();
```

### Periodic Sync

You can automatically sync at intervals by configuring the `syncIntervalSeconds` property when instantiating the client:

```dart
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';

final client = LibsqlClient(path)
	..authToken = '<TOKEN>'
	..syncUrl = '<TURSO_OR_LIBSQL_URL>'
	..syncIntervalSeconds = 5
	..readYourWrites = true;
```

### Encryption at rest

To enable encryption on a SQLite file, pass the `encryptionKey`:

```dart
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';

final client = LibsqlClient(path)..encryptionKey = '<KEY>';
```

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](/libsql#encryption-at-rest).

## Execute

Returns number of rows affected:

```dart
await client.execute("create table if not exists customers (id integer primary key, name text);");
```

## Query

Returns rows as `List<Map<String, dynamic>>`. Will returns empty list when is not performing select query:

```dart
await client.query("insert into customers(name) values ('John Doe')");

print(await client.query("select * from customers"));
```

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```dart Positional
  final statement = await client
  	.prepare("select * from customers where id = ?");

  await statement.query(positional: [1])
  ```

  ```dart Named
  final statement = await client
  	.prepare("select * from customers where id = :id");

  await statement.query(named: {"id": 1})
  ```
</CodeGroup>

<br />

<Info>
  libSQL supports the same named placeholder characters as SQLite — `:`, `@` and `$`.
</Info>

## Batch Transactions

A batch consists of multiple SQL statements executed sequentially within an implicit transaction. The backend handles the transaction: success commits all changes, while any failure results in a full rollback with no modifications.

```dart
await client.batch("""insert into customers (name) values ('Jane Doe'); insert into customers (name) values ('Jake Doe');""");
```

## Transaction Modes

| Mode                                  | SQLite command               | Description                                                                                                                                                                                        |
| ------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LibsqlTransactionBehavior.immediate` | `BEGIN IMMEDIATE`            | The transaction may execute statements that read and write data. Write transactions executed on a replica are forwarded to the primary instance, and can't operate in parallel.                    |
| `LibsqlTransactionBehavior.readOnly`  | `BEGIN TRANSACTION READONLY` | The transaction may only execute statements that read data (select). Read transactions can occur on replicas, and can operate in parallel with other read transactions.                            |
| `LibsqlTransactionBehavior.deferred_` | `BEGIN DEFERRED`             | The transaction starts in read mode, then changes to write as soon as a write statement is executed. This mode change may fail if there is a write transaction currently executing on the primary. |

## Interactive Transactions

Interactive transactions in SQLite ensure the consistency of a series of read and write operations within a transaction's scope. These transactions give you control over when to commit or roll back changes, isolating them from other client activity.

| Method       | Description                                                         |
| ------------ | ------------------------------------------------------------------- |
| `execute()`  | Similar to `execute()` except within the context of the transaction |
| `query()`    | Similar to `query()` except within the context of the transaction   |
| `commit()`   | Commits all write statements in the transaction                     |
| `rollback()` | Rolls back the entire transaction                                   |

```dart
final tx = await client.transaction();

await tx
	.execute("update customers set name = 'John Noe' where id = 1");
await tx
	.execute("update customers set name = 'Jane Noe' where id = 2");
print(await tx
	.query("select * from customers where id = ?", positional: [1]));

await tx.commit();
```

<br />

<Warning>
  Interactive transactions in libSQL lock the database for writing until
  committed or rolled back, with a 5-second timeout. They can impact performance
  on high-latency or busy databases.
</Warning>

## ATTACH

You can attach multiple databases to the current connection using the `ATTACH` attachment:

```dart
final tx = await client.transaction(behavior: LibsqlTransactionBehavior.readOnly);

await tx.execute("ATTACH "<database-id>" AS attached");

print(await tx.execute("SELECT * FROM attached.customers"));

await tx.commit();
```

<Info>
  Make sure to [allow `ATTACH`](/cli/db/config/attach/allow) and create a token
  with the permission to attach a database — [learn
  more](/features/attach-database)
</Info>


# Examples





# Turso Quickstart (Go)

Get started with Turso and Go using the libSQL client in a few simple steps.

The libSQL package is designed to work with [`database/sql`](https://pkg.go.dev/database/sql) to provide the usual methods you'd expect when working with databases in Go.

<Info>
  The `go-libsql` package uses CGO. You can use `github.com/tursodatabase/libsql-client-go/libsql` instead, but it doesn't support embedded replicas.
</Info>

In this Go quickstart we will learn how to:

*   Retrieve database credentials
*   Install Go libSQL
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install">
    First begin by adding libSQL to your project:

    <AccordionGroup>
      <Accordion title="Local / Embedded Replicas">
        ```bash
        go get github.com/tursodatabase/go-libsql
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```bash
        go get github.com/tursodatabase/libsql-client-go/libsql
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Connect">
    Now connect to your local or remote database using the libSQL connector:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```go
        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()
        }
        ```
      </Accordion>

      <Accordion title="Local only">
        ```go
        package main

        import (
          "database/sql"
          "fmt"
          "os"

          _ "github.com/tursodatabase/go-libsql"
        )

        func main() {
          dbName := "file:./local.db"

          db, err := sql.Open("libsql", dbName)
          if err != nil {
            fmt.Fprintf(os.Stderr, "failed to open db %s", err)
            os.Exit(1)
          }
          defer db.Close()
        }
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```go
        package main

        import (
          "database/sql"
          "fmt"
          "os"

          _ "github.com/tursodatabase/libsql-client-go/libsql"
        )

        func main() {
          url := "libsql://[DATABASE].turso.io?authToken=[TOKEN]"

          db, err := sql.Open("libsql", url)
          if err != nil {
            fmt.Fprintf(os.Stderr, "failed to open db %s: %s", url, err)
            os.Exit(1)
          }
          defer db.Close()
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database. Create a function to query your database that accepts the pointer to `sql.DB` as an argument:

    ```go
    type User struct {
    	ID   int
    	Name string
    }

    func queryUsers(db *sql.DB)  {
      rows, err := db.Query("SELECT * FROM users")
      if err != nil {
        fmt.Fprintf(os.Stderr, "failed to execute query: %v\n", err)
        os.Exit(1)
      }
      defer rows.Close()

      var users []User

      for rows.Next() {
        var user User

        if err := rows.Scan(&user.ID, &user.Name); err != nil {
          fmt.Println("Error scanning row:", err)
          return
        }

        users = append(users, user)
        fmt.Println(user.ID, user.Name)
      }

      if err := rows.Err(); err != nil {
        fmt.Println("Error during rows iteration:", err)
      }
    }
    ```

    Now inside `func main()` call `queryUsers` and pass in the pointer to `sql.DB`:

    ```go
    queryUsers(db)
    ```
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `Sync()` on the connector to sync your local database with the primary database.

    ```go
    if err := connector.Sync(); err != nil {
      fmt.Println("Error syncing database:", err)
    }
    ```

    The connector can automatically sync your database at a regular interval when using the `WithSyncInterval` option:

    ```go
    syncInterval := time.Minute

    connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
        libsql.WithAuthToken(authToken),
        libsql.WithSyncInterval(syncInterval),
    )
    ```
  </Step>
</Steps>


# Reference



## Embedded Replicas

You can work with [embedded replicas](/features/embedded-replicas) that can sync from the remote database to a local SQLite file, and delegate writes to the remote primary database:

```go
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()
}
```

<Snippet file="embedded-replicas-warning.mdx" />

### Manual Sync

The `Sync` function allows you to sync manually the local database with the remote counterpart:

```go
if err := connector.Sync(); err != nil {
    fmt.Println("Error syncing database:", err)
}
```

### Periodic Sync

You can automatically sync at intervals using `WithSyncInterval` and passing a `time.Duration` as an argument. For example, to sync every minute, you can use the following code:

```go
syncInterval := time.Minute

connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithSyncInterval(syncInterval),
)
```

### Read Your Writes

By default, the database connection ensures that writes are immediately visible to subsequent read operations initiated by the same connection.

You can disable this behaviour using `WithReadYourWrites(false)`:

```go
connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithReadYourWrites(false),
)
```

## Encryption

To enable encryption on a SQLite file, pass the encryption key value as an argument to the constructor:

```go
encryptionKey := "SuperSecretKey"

connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithEncryption(encryptionKey),
)
```

<Info>
  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](/libsql#encryption-at-rest).
</Info>


# Turso Quickstart (HTTP)

Get started with Turso using the libSQL remote protocol in a few simple steps.

In this HTTP quickstart we will learn how to:

*   Obtain HTTP URL for a Turso database
*   Create a database auth token
*   Connect to a remote Turso database
*   Execute a SQL using the [libSQL remote protocol](https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md#hrana-over-http)

<Steps>
  <Step title="Create HTTP Database URL">
    Using the [Turso CLI](/cli) or [Platform API](/api-reference), fetch your database URL:

    ```bash
    turso db show <database-name> --http-url
    ```

    <Info>
      Append `/v2/pipeline` to the URL and continue.
    </Info>
  </Step>

  <Step title="Create Database Auth Token">
    Using the Turso CLI or Platform API, create a new auth token for your database:

    ```bash
    turso db tokens create <database-name>
    ```
  </Step>

  <Step title="Create JSON Request Payload">
    We'll be sending the query using JSON, so let's create a JSON payload that executes a SQL statement and closes the connection immediately:

    ```json
    {
      "requests": [
        { "type": "execute", "stmt": { "sql": "SELECT * FROM users" } },
        { "type": "close" }
      ]
    }
    ```

    <Info>
      Make sure to update the `stmt.sql` to select from a table you already have.

      Bound parameter examples included on the [Reference Page](/sdk/http/reference#parameter-binding),
    </Info>
  </Step>

  <Step title="Execute HTTP Request">
    Depending on your language, you can use a HTTP client library to send the request to the URL you created as well as the `Authorization` header set to the token you created, and the request body as JSON with your SQL statement.

    You must append to the Base URL the actual pipeline URL that accepts requests — `/v2/pipeline`.

    <CodeGroup>
      ```ts JavaScript (Fetch)
      const url = "https://[databaseName]-[organizationName].turso.io/v2/pipeline";
      const authToken = "...";

      fetch(url, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${authToken}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          requests: [
            { type: "execute", stmt: { sql: "SELECT * FROM users" } },
            { type: "close" },
          ],
        }),
      })
        .then((res) => res.json())
        .then((data) => console.log(data))
        .catch((err) => console.log(err));
      ```

      ```ruby Ruby
      require 'net/http'
      require 'json'
      require 'uri'

      url = "https://[databaseName]-[organizationName].turso.io/v2/pipeline"
      auth_token = "..."

      uri = URI(url)
      request = Net::HTTP::Post.new(uri)
      request["Authorization"] = "Bearer #{auth_token}"
      request["Content-Type"] = "application/json"
      request.body = JSON.generate({
        "requests": [
          { "type": "execute", "stmt": { "sql": "SELECT * FROM users" } },
          { "type": "close" }
        ]
      })

      begin
        response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
          http.request(request)
        end

        puts JSON.parse(response.body)
      rescue => e
        puts e.message
      end
      ```
    </CodeGroup>

    <br />

    <Accordion title="Response">
      The response will be a JSON object with a `results` array containing the results of your query that looks something like this:

      ```json
      {
        "baton": null,
        "base_url": null,
        "results": [
          {
            "type": "ok",
            "response": {
              "type": "execute",
              "result": {
                "cols": [],
                "rows": [],
                "affected_row_count": 0,
                "last_insert_rowid": null,
                "replication_index": "1"
              }
            }
          },
          {
            "type": "ok",
            "response": {
              "type": "close"
            }
          }
        ]
      }
      ```
    </Accordion>

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```json Positional
      {
        "type": "execute",
        "stmt": {
          "sql": "SELECT * FROM users WHERE id = ?",
          "args": [
            {
              "type": "integer",
              "value": "1"
            }
          ]
        }
      }
      ```

      ```json Named
      {
        "type": "execute",
        "stmt": {
          "sql": "SELECT * FROM users WHERE name = :name OR name = $second_name OR name = @third_name",
          "named_args": [
            {
              "name": "name",
              "value": {
                "type": "text",
                "value": "Turso"
              }
            },
            {
              "name": "second_name",
              "value": {
                "type": "text",
                "value": "Not Turso"
              }
            },
            {
              "name": "third_name",
              "value": {
                "type": "text",
                "value": "Maybe Turso"
              }
            }
          ]
        }
      }
      ```
    </CodeGroup>

    <Info>
      The `type` field within each arg corresponds to the column datatype and can be one of the following: `null`, `integer`, `float`, `text`, or `blob`.
    </Info>

    <Note>
      In JSON, the `value` is a `String` to avoid losing precision, because some
      JSON implementations treat all numbers as 64-bit floats.
    </Note>
  </Step>
</Steps>


# libSQL Remote Protocol Reference



Turso Databases can be accessed via HTTP. The API enable developers to perform SQL operations using the [libSQL remote protocol](https://github.com/tursodatabase/libsql/blob/main/docs/HTTP_V2_SPEC.md), retrieve server version information, and monitor the health status.

<Info>
  It's recommended you use a [native SDK](/sdk).
</Info>

## Base URL

Simply replace your database URL protocol `libsql://` with `https://`:

```bash
https://[databaseName]-[organizationName].turso.io
```

You can obtain your database base URL from the Turso CLI:

<Accordion title="Obtain HTTP URL using Turso CLI">
  ```bash
  turso db show <database-name> --http-url
  ```
</Accordion>

## Authentication

Turso uses Bearer authentication, and requires your API token to be passed with all protected requests in the `Authorization` header:

```bash
Authorization: Bearer TOKEN
```

<Accordion title="Create token using Turso CLI">
  ```bash
  turso db tokens create <database-name>
  ```
</Accordion>

## Endpoints

Your database has the endpoints available below:

### `POST /v2/pipeline`

You can use the `/v2/pipeline` endpoint to query a database. The endpoint accepts a series of operations to perform against a database connection. The supported operation types are:

*   `execute`: execute a statement on the connection.
*   `close`: close the connection.

#### Simple query

<CodeGroup>
  ```json Request
  {
    "requests": [
      { "type": "execute", "stmt": { "sql": "CREATE TABLE users (name)" } },
      { "type": "close" }
    ]
  }
  ```

  ```json Response
  {
    "baton": null,
    "base_url": null,
    "results": [
      {
        "type": "ok",
        "response": {
          "type": "execute",
          "result": {
            "cols": [],
            "rows": [],
            "affected_row_count": 0,
            "last_insert_rowid": null,
            "replication_index": "1"
          }
        }
      },
      {
        "type": "ok",
        "response": {
          "type": "close"
        }
      }
    ]
  }
  ```
</CodeGroup>

<br />

<Info>
  Connections are left open until they timeout, unless you close them explicitly in the request (as shown above). Every request made on a connection bumps the timeout. You should close the connection when it's no longer needed.
</Info>

#### Parameter binding

Queries with bound parameters come in two types:

1.  Positional query parameters, bound by their position in the parameter list, and prefixed `?`. If the query uses positional parameters, the values should be provided as an array to the `args` field.

<CodeGroup>
  ```json Request
  {
    "requests": [
      {
        "type": "execute",
        "stmt": {
          "sql": "SELECT * FROM users WHERE name = ?",
          "args": [
            {
              "type": "text",
              "value": "Turso"
            }
          ]
        }
      },
      {
        "type": "close"
      }
    ]
  }
  ```

  ```json Response
  {
    "baton": null,
    "base_url": null,
    "results": [
      {
        "type": "ok",
        "response": {
          "type": "execute",
          "result": {
            "cols": [
              {
                "name": "name",
                "decltype": "TEXT"
              }
            ],
            "rows": [
              [
                {
                  "type": "text",
                  "value": "Turso"
                }
              ]
            ],
            "affected_row_count": 0,
            "last_insert_rowid": null
          }
        }
      },
      {
        "type": "ok",
        "response": {
          "type": "close"
        }
      }
    ]
  }
  ```
</CodeGroup>

<br />

2.  Named bound parameters, where the parameter is referred to by a name and is prefixed with a `:`, a `@` or a `$`. If the query uses named parameters, then the `named_args` field of the query should be an array of objects mapping parameters to their values.

<CodeGroup>
  ```json Request
  {
    "requests": [
      {
        "type": "execute",
        "stmt": {
          "sql": "SELECT * FROM users WHERE name = :name OR name = $second_name OR name = @third_name",
          "named_args": [
            {
              "name": "name",
              "value": {
                "type": "text",
                "value": "Turso"
              }
            },
            {
              "name": "second_name",
              "value": {
                "type": "text",
                "value": "Not Turso"
              }
            },
            {
              "name": "third_name",
              "value": {
                "type": "text",
                "value": "Maybe Turso"
              }
            }
          ]
        }
      },
      {
        "type": "close"
      }
    ]
  }
  ```

  ```json Response
  {
    "baton": null,
    "base_url": null,
    "results": [
      {
        "type": "ok",
        "response": {
          "type": "execute",
          "result": {
            "cols": [
              {
                "name": "name",
                "decltype": "TEXT"
              }
            ],
            "rows": [
              [
                {
                  "type": "text",
                  "value": "Turso"
                }
              ]
            ],
            "affected_row_count": 0,
            "last_insert_rowid": null
          }
        }
      },
      {
        "type": "ok",
        "response": {
          "type": "close"
        }
      }
    ]
  }
  ```
</CodeGroup>

<br />

<Info>
  The `name` property of each `named_args` can match the prefix or omit the prefix. They were omitted in the example above, but both versions are valid.

  The `type` field within each arg corresponds to the column datatype and can be one of the following: `null`, `integer`, `float`, `text`, or `blob`.
</Info>

<Info>
  If using the `blob` type, replace the `value` property with `base64` and encode the argument into `base64` before sending the request.
</Info>

<Note>
  In JSON, the `value` is a `String` to avoid losing precision, because some
  JSON implementations treat all numbers as 64-bit floats.
</Note>

#### Interactive query

Sometimes, it may be desirable to perform multiple operation on the same connection, in multiple roundtrips. We can do this by not closing the connection right away:

<CodeGroup>
  ```json Body
  {
    "requests": [{ "type": "execute", "stmt": { "sql": "BEGIN" } }]
  }
  ```

  ```json Response
  {
    "baton": "m7lVVgEvknpf1P1irxHsHqrAqH7BLiwO4DQIAwr93PdZWGvdBNugLSokSsCZNkry",
    "base_url": null,
    "results": [
      {
        "type": "ok",
        "response": {
          "type": "execute",
          "result": {
            "cols": [],
            "rows": [],
            "affected_row_count": 0,
            "last_insert_rowid": null,
            "replication_index": "1"
          }
        }
      }
    ]
  }
  ```
</CodeGroup>

We can see that we have received a `baton` back. This is because we haven't closed the connection. We can now use this baton to perform more queries on the same connection:

```json Body
{
  "baton": "m7lVVgEvknpf1P1irxHsHqrAqH7BLiwO4DQIAwr93PdZWGvdBNugLSokSsCZNkry",
  "requests": [
    { "type": "execute", "stmt": { "sql": "CREATE TABLE users (name)" } },
    {
      "type": "execute",
      "stmt": { "sql": "INSERT INTO users VALUES (\"iku\")" }
    },
    { "type": "execute", "stmt": { "sql": "COMMIT" } },
    { "type": "close" }
  ]
}
```

<Info>
  Note that both transactions and connections have timeouts. Transaction have a 5 seconds window to complete, while connections get closed after 10 seconds of idle time.
</Info>

#### Response types

The response contains the following fields:

| Field      | Type   | Description                                                                                                                          |
| ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `baton`    | string | The baton is used to identify a connection with the server so that it can be reused.                                                 |
| `base_url` | string | The base URL of the server that handled the request. This URL can be reused for subsequent requests to force routing to that server. |
| `results`  | array  | The results for each of the requests made in the pipeline.                                                                           |

The `results` array contains the results for each of the requests made in the pipeline. Each result has the following fields:

| Field                | Type    | Description                                                 |
| -------------------- | ------- | ----------------------------------------------------------- |
| `cols`               | array   | The list of columns for the returned rows.                  |
| `rows`               | array   | The rows returned for the query.                            |
| `affected_row_count` | integer | The number of rows affected by the query.                   |
| `last_insert_rowid`  | integer | The ID of the last inserted row.                            |
| `replication_index`  | string  | The replication timestamp at which this query was executed. |
| `rows_read`          | integer | The number of rows read by the query.                       |
| `rows_written`       | integer | The number of rows written by the query.                    |
| `query_duration_ms`  | float   | The duration of the query in milliseconds.                  |

### `GET /version`

To obtain the current version of the server running your database you can use the `/version` endpoint:

<CodeGroup>
  ```bash Request
  curl -L -X GET 'https://[databaseName]-[organizationName].turso.io/version' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```text 200
  sqld 0.21.9 (67f3ea5d 2023-10-26)
  ```
</CodeGroup>

### `GET /health`

To check the health of your database, you can use the `/health` endpoint which returns an empty body with an HTTP status:

<CodeGroup>
  ```bash Request
  curl -L -X GET 'https://[databaseName]-[organizationName].turso.io/health' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```text 200
  This response has no body data.
  ```
</CodeGroup>

### `GET /dump`

You can dump the database using the `/dump` endpoint:

<CodeGroup>
  ```bash Request
  curl -L -X GET 'https://[databaseName]-[organizationName].turso.io/dump' \
    -H 'Authorization: Bearer TOKEN'
  ```

  ```text 200
  PRAGMA foreign_keys=OFF;
  BEGIN TRANSACTION;
  CREATE TABLE IF NOT EXISTS mytable (
  content TEXT,
  embedding FLOAT32(1536)
  );
  CREATE TABLE IF NOT EXISTS libsql_vector_index (type TEXT, name TEXT, vector_type TEXT, block_size INTEGER, dims INTEGER, distance_ops TEXT);
  INSERT INTO libsql_vector_index VALUES('diskann','mytable_idx','float32',128,1536,'cosine');
  CREATE INDEX mytable_idx USING diskann_cosine_ops ON mytable (embedding);
  COMMIT;
  ```
</CodeGroup>

If you're using [multi-db schemas](/features/multi-db-schemas), or vector databases, you will see statements that represent internally managed tables.

### `GET /beta/listen`

<Snippet file="technical-preview-banner.mdx" />

You can listen to changes committed to your database using the `/beta/listen` endpoint:

```bash Request
curl -L 'https://[primary-instance-id]-[databaseName]-[organizationName].turso.io/beta/listen?table=TABLE_NAME' \
-H 'Authorization: Bearer TOKEN'
```

#### Query Parameters

*   `table` (required) — The name of the table to listen to.
*   `action` (optional) — The action to listen to, `insert`, `update`, or `delete`.

<Info>
  Your database group must be using the version `v0.24.18` or greater — `turso group update <group-name> --version latest`
</Info>


# Introduction



Turso provides multiple official SDKs that you can use to connect a local or remote database, as well as support for embedded databases. If you're using a language or framework that isn't supported with an official driver, you can use Turso over HTTP.

## Official SDKs

Turso SDKs are fully compatible with [libSQL](/libsql), so you can use the same SDK to connect to a local database ([SQLite](/local-development#sqlite)), [libSQL server](/local-development#libsql-server), a remote database, or an [embedded replica](/features/embedded-replicas).

<Snippet file="official-sdks.mdx" />

## Community SDKs

These SDKs are community-driven and don't come with official Turso support.

<CardGroup cols={2}>
  <Card
    horizontal
    title="Flutter / Dart"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
       <path
         fill="#1ebca1"
         d="M429.5 236.3L291.7 374.1 429.5 512H272l-59.1-59.1-78.8-78.8L272 236.3H429.5zM272 0L16 256l78.8 78.8L429.5 0H272z"
       />
     </svg>
    }
    href="/sdk/flutter/quickstart"
  />

  <Card horizontal title="React Native / OP-SQLite" icon="react" href="https://ospfranco.notion.site/OP-SQLite-Documentation-a279a52102464d0cb13c3fa230d2f2dc?pvs=4" />

  <Card
    horizontal
    title="Laravel"
    icon={
     <svg
       xmlns="http://www.w3.org/2000/svg"
       preserveAspectRatio="xMidYMid"
       viewBox="0 0 256 264"
     >
       <path
         d="m255.9 59.6.1 1.1v56.6c0 1.4-.8 2.8-2 3.5l-47.6 27.4v54.2c0 1.4-.7 2.8-2 3.5l-99.1 57-.7.4-.3.1c-.7.2-1.4.2-2.1 0l-.4-.1-.6-.3L2 206c-1.3-.8-2.1-2.2-2.1-3.6V32.7l.1-1.1.2-.4.3-.6.2-.4.4-.5.4-.3c.2 0 .3-.2.5-.3L51.6.6c1.3-.8 2.9-.8 4.1 0L105.3 29c.2 0 .3.2.4.3l.5.3c0 .2.2.4.3.5l.3.4.3.6.1.4.2 1v106l41.2-23.7V60.7c0-.4 0-.7.2-1l.1-.4.3-.7.3-.3.3-.5.5-.3.4-.4 49.6-28.5c1.2-.7 2.8-.7 4 0L254 57l.5.4.4.3.4.5.2.3c.2.2.2.5.3.7l.2.3Zm-8.2 55.3v-47l-17.3 10-24 13.7v47l41.3-23.7Zm-49.5 85v-47l-23.6 13.5-67.2 38.4v47.5l90.8-52.3ZM8.2 39.9V200l90.9 52.3v-47.5l-47.5-26.9-.4-.4c-.2 0-.3-.1-.4-.3l-.4-.4-.3-.4-.2-.5-.2-.5v-.6l-.2-.5V63.6L25.6 49.8l-17.3-10Zm45.5-31L12.4 32.8l41.3 23.7 41.2-23.7L53.7 8.9ZM75 157.3l24-13.8V39.8l-17.3 10-24 13.8v103.6l17.3-10ZM202.3 36.9 161 60.7l41.3 23.8 41.3-23.8-41.3-23.8Zm-4.1 54.7-24-13.8-17.3-10v47l24 13.9 17.3 10v-47Zm-95 106 60.6-34.5 30.2-17.3-41.2-23.8-47.5 27.4L62 174.3l41.2 23.3Z"
         fill="#1ebca1"
       />
     </svg>
    }
    href="https://github.com/richan-fongdasen/turso-laravel"
  />

  <Card horizontal title=".NET" icon="microsoft" href="https://github.com/tvandinther/libsql-client-dotnet" />

  <Card horizontal title="Stateless libSQL" icon="github" href="https://github.com/DaBigBlob/libsql-stateless-easy" />
</CardGroup>

## Turso over HTTP

<CardGroup cols={2}>
  <Snippet file="http-sdk.mdx" />
</CardGroup>


# Turso Quickstart (Android)

Get started with Turso and Android using the libSQL client in a few simple steps.

<Snippet file="technical-preview-banner.mdx" />

<Note>
  This will only work with the Android Gradle Plugin for now. Fully Kotlin
  support is coming.
</Note>

In this Kotlin quickstart we will learn how to:

*   Retrieve database credentials
*   Add libSQL as a dependency in your Android Gradle project
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Snippet file="mobile-secrets-warning.mdx" />
  </Step>

  <Step title="Install">
    Add libsql as a implementation dependency in Gradle:

    <Note>
      This will only work with the Android Gradle Plugin for now.
    </Note>

    ```kotlin
    dependencies {
        implementation("tech.turso.libsql:libsql:0.1.0")
    }
    ```
  </Step>

  <Step title="Connect">
    You must first create a `Database` object and then open a `Connection` to it:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```kotlin
        import tech.turso.libsql.Libsql

        val db = Libsql.open(
            path = "./local.db",
            url = "TURSO_DATABASE_URL",
            authToken = "TURSO_AUTH_TOKEN",
        )

        val conn = db.connect()
        ```
      </Accordion>

      <Accordion title="Local only">
        ```kotlin
        import tech.turso.libsql.Libsql

        val db = Libsql.open(path = "./local.db")
        val conn = db.connect()
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```kotlin
        import tech.turso.libsql.Libsql

        val db = Libsql.open(
            url = "TURSO_DATABASE_URL",
            authToken = "TURSO_AUTH_TOKEN",
        )

        val conn = db.connect()
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database by calling `execute()`:

    ```kotlin
    db.connect().use {
        it.execute("INSERT INTO users (id) VALUES (1)")
    }
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```kotlin Positional
      db.connect().use {
          it.query("SELECT * FROM users WHERE id = ?", 1)
      }
      ```

      ```kotlin Named
      db.connect().use {
          it.query("INSERT INTO users (name) VALUES (:name)", mapOf(":name" to "Iku"))
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the database type to
    sync your local database with the primary database, unless you are using
    `syncInterval` (though there is no issue with calling `sync` with
    `syncInterval` enabled):

    ```kotlin
    db.sync()
    ```
  </Step>
</Steps>


# Android Reference

libSQL Android Reference

<Snippet file="technical-preview-banner.mdx" />

<Note>
  This will only work with the Android Gradle Plugin for now. Fully Kotlin
  support is coming.
</Note>

## Installing

Add libsql as a implementation dependency in Gradle:

```kotlin
dependencies {
    implementation("tech.turso.libsql:libsql:0.1.0")
}
```

## In-Memory Databases

libSQL supports connecting to [in-memory
databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't
require persistence:

```kotlin
import tech.turso.libsql.Libsql

val db = Libsql.open(":memory:")
val conn = db.connect()
```

## Local Development

You can work locally using an SQLite file:

```kotlin
import tech.turso.libsql.Libsql

val db = Libsql.open(path = "./local.db")
val conn = db.connect()
```

## Embedded Replicas

You can work with embedded replicas that can sync from the remote URL and
delegate writes to the remote primary database:

```kotlin
import tech.turso.libsql.Libsql

val db = Libsql.open(
    path = "./local.db",
    url = "TURSO_DATABASE_URL",
    authToken = "TURSO_AUTH_TOKEN",
)

val conn = db.connect()
```

### Manual Sync

The `sync` function allows you to sync manually the local database with the
remote counterpart:

```kotlin
db.sync() // Call sync manually to update local database (only for EmbeddedReplicaDatabase)
```

## Simple query

You can pass a string to `query()` to invoke a SQL statement, as well as
optional arguments:

<CodeGroup>
  ```kotlin Execute
  db.connect().use {
      it.execute("INSERT INTO users VALUES (?)", 1)
  }
  ```

  ```kotlin Query
  db.connect().use {
      it.query("INSERT INTO users VALUES (?)", 1)
  }
  ```

  ```kotlin Arguments
  db.connect().use {
      it.query("SELECT * FROM users WHERE id = ?", 1)
  }
  ```
</CodeGroup>

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

```kotlin Positional
db.connect().use {
    it.query("SELECT * FROM users WHERE id = ?", 1)
}
```

```kotlin Named
db.connect().use {
    it.query("SELECT * FROM users WHERE id = :id", mapOf(":id" to 1))
}
```

## Batch Transactions

A batch consists of multiple SQL statements executed sequentially within an
implicit transaction. The backend handles the transaction: success commits all
changes, while any failure results in a full rollback with no modifications.

```kotlin
db.connect().use {
    it.execute_batch("
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL
      );

      INSERT INTO users (name) VALUES ('Alice');
      INSERT INTO users (name) VALUES ('Bob');
    ")
}
```

## Transactions

Interactive transactions in SQLite ensure the consistency of a series of read
and write operations within a transaction's scope. These transactions give you
control over when to commit or roll back changes, isolating them from other
client activity.

```kotlin
db.connect().use {
    val tx = it.transaction();

    tx.execute("INSERT INTO users (name) VALUES (?)", "Iku");
    tx.execute("INSERT INTO users (name) VALUES (?)", "Iku 2");

    tx.commit() // or tx.rollback()
}
```


# Examples



[View examples on GitHub](https://github.com/tursodatabase/libsql-client-ts/tree/main/packages/libsql-client/examples)


# Turso + Laravel

Set up Turso in your Laravel project in minutes

![Laravel Banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/laravel-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Laravel Application

<Snippet file="install-libsql-extension-php.mdx" />

<Steps>
  <Step title="Configure database credentials">
    Get the database URL:

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token:

    ```bash
    turso db tokens create <database-name>
    ```

    Assign credentials to the environment variables inside `.env`.

    ```bash
    DB_SYNC_URL=
    DB_AUTH_TOKEN=
    ```

    <Info>Save this later when you need to connect to **Remote** and **Embedded Replica**</Info>
  </Step>

  <Step title="Create Laravel Project">
    Using Composer:

    ```bash
    composer create-project laravel/laravel turso-laravel
    ```

    If you already have laravel installer:

    ```bash
    laravel new turso-laravel
    ```
  </Step>

  <Step title="Install Turso Driver Laravel">
    Install `turso-driver-laravel`:

    ```bash
    composer require tursodatabase/turso-driver-laravel
    ```

    Add this `LibSQLServiceProvider` class at `bootstrap/providers.php`:

    ```php
    Turso\Driver\Laravel\LibSQLDriverServiceProvider::class
    ```
  </Step>

  <Step title="Configure database connection">
    Setup the environment variable in your Laravel application, choose what the type connection you need.

    <CodeGroup>
      ```bash In-Memory Only
      DB_CONNECTION=libsql
      DB_DATABASE=:memory:
      ```

      ```bash Local Only
      DB_CONNECTION=libsql
      DB_DATABASE=database.sqlite
      ```

      ```bash Remote Only
      DB_CONNECTION=libsql
      DB_AUTH_TOKEN=<your-database-auth-token-from-turso>
      DB_SYNC_URL=<your-database-url-from-turso>
      DB_REMOTE_ONLY=true
      ```

      ```bash Embedded Replica
      DB_CONNECTION=libsql
      DB_DATABASE=database.sqlite
      DB_AUTH_TOKEN=<your-database-auth-token-from-turso>
      DB_SYNC_URL=<your-database-url-from-turso>
      ```
    </CodeGroup>

    **Other environment variables (Embedded Replica Only)**

    <Expandable title="Other environment variables (Embedded Replica Only)">
      <ResponseField name="DB_SYNC_INTERVAL" type="integer">
        Integer value representing synchronization interval in seconds (optional, default: `5`).
      </ResponseField>

      <ResponseField name="DB_READ_YOUR_WRITES" type="boolean">
        Boolean value indicating whether to read your writes (optional, default: `true`).
      </ResponseField>

      <ResponseField name="DB_ENCRYPTION_KEY" type="string">
        String value for encryption purposes (optional, default: empty).
      </ResponseField>

      <ResponseField name="DB_REMOTE_ONLY" type="boolean">
        This variable is define to use remote connection only, if you only want to read and write the database from remote database (optional, default: false).
      </ResponseField>
    </Expandable>
  </Step>

  <Step title="Database configuration">
    Add this configuration at `config/database.php` inside the `connections` array:

    ```php
    'libsql' => [
        'driver' => 'libsql',
        'url' => env('DB_DATABASE', 'database.sqlite'),
        'authToken' => env('DB_AUTH_TOKEN', ''),
        'syncUrl' => env('DB_SYNC_URL', ''),
        'syncInterval' => env('DB_SYNC_INTERVAL', 5),
        'read_your_writes' => env('DB_READ_YOUR_WRITES', true),
        'encryptionKey' => env('DB_ENCRYPTION_KEY', ''),
        'remoteOnly' => env('DB_REMOTE_ONLY', false),
        'database' => null,
        'prefix' => '',
    ],
    ```

    <Note>**Copy and Paste and do not change it!** Or try to change it and will broke your app or give you malfunction.</Note>
  </Step>

  <Step title="Create database seeders">
    In fresh Laravel installation, your can open file `database/seeders/DatabaseSeeder.php` and change the code with this:

    ```php
    <?php

    namespace Database\Seeders;

    use App\Models\User;
    // use Illuminate\Database\Console\Seeds\WithoutModelEvents;
    use Illuminate\Database\Seeder;

    class DatabaseSeeder extends Seeder
    {
        /**
        * Seed the application's database.
        */
        public function run(): void
        {
            // We will create 10 fake users
            User::factory(10)->create();
        }
    }

    ```

    then create the database seeders:

    ```bash
    php artisan db:seed --class=DatabaseSeeder
    ```
  </Step>

  <Step title="Execute Query">
    <CodeGroup>
      ```php Create
      DB::table('users')->insert([
          'name' => 'Budi Dalton',
          'email' => 'budi.dalton@duck.com'
      ]);
      ```

      ```php Read
      DB::table('users')->get();
      DB::table('users')->where('id', 2)->first();
      DB::table('users')->orderBy('id', 'DESC')->limit(2)->get();
      ```

      ```php Update
      DB::table('users')->where('id', 2)->update(['name' => 'Doni Mandala']);
      ```

      ```php Delete
      DB::table('users')->where('id', 2)->delete();
      ```

      ```php Transaction
      try {
          DB::beginTransaction();

          $updated = DB::table('users')->where('id', 9)->update(['name' => 'Doni Kumala']);

          if ($updated) {
              echo "It's updated";
              DB::commit();
          } else {
              echo "Not updated";
              DB::rollBack();
          }

          $data = DB::table('users')->orderBy('id', 'DESC')->limit(2)->get();
          dump($data);
      } catch (\Exception $e) {
          DB::rollBack();
          echo "An error occurred: " . $e->getMessage();
      }
      ```

      ```php Sync (Embedded Only)
      DB::sync();
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Laravel Authenticated Todo List - Breeze + Livewire Volt" icon="github" href="https://github.com/tursodatabase/examples/tree/master/laravel-authenticated-todo-list">
    See the full source code
  </Card>
</CardGroup>


# Turso + Doctrine DBAL

Set up Turso in your PHP + Doctrine DBAL project in minutes

![Doctrine DBAL](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/doctrine-dbal-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an PHP Application with Doctrine DBAL

<Snippet file="install-libsql-extension-php.mdx" />

<Steps>
  <Step title="Configure database credentials">
    Get the database URL:

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token:

    ```bash
    turso db tokens create <database-name>
    ```

    Assign credentials to the environment variables inside `.env`.

    ```bash
    TURSO_DATABASE_URL=
    TURSO_AUTH_TOKEN=
    ```

    <Info>Save this later when you need to connect to **Remote** and **Embedded Replica**</Info>
  </Step>

  <Step title="Create PHP Project">
    Create new directory:

    ```bash
    mkdir your-awesome-php-project
    cd your-awesome-php-project
    ```
  </Step>

  <Step title="Install Turso Doctrine DBAL">
    ```bash
    composer require tursodatabase/turso-doctrine-dbal
    ```
  </Step>

  <Step title="Configure database connection">
    Setup the environment variable in your Laravel application, choose what the type connection you need.

    <CodeGroup>
      ```php In-Memory Only
      $params = [
          "url"               => ":memory:",
          'driverClass'       => \Turso\Doctrine\DBAL\Driver::class,
      ];
      ```

      ```php Local Only
      $params = [
          "url"               => "database.db",
          'driverClass'       => \Turso\Doctrine\DBAL\Driver::class,
      ];
      ```

      ```php Remote Only
      $params = [
          "auth_token"        => getenv('TURSO_AUTH_TOKEN'),
          "sync_url"          => getenv('TURSO_DATABASE_URL'),
          'driverClass'       => \Turso\Doctrine\DBAL\Driver::class,
      ];
      ```

      ```php Embedded Replica
      $params = [
          "url"               => "database.db",
          "auth_token"        => getenv('TURSO_AUTH_TOKEN'),
          "sync_url"          => getenv('TURSO_DATABASE_URL'),
          'driverClass'       => \Turso\Doctrine\DBAL\Driver::class,
      ];
      ```
    </CodeGroup>

    **Other environment variables (Embedded Replica Only)**

    <Expandable title="Other environment variables (Embedded Replica Only)">
      <ResponseField name="sync_interval" type="integer">
        Integer value representing synchronization interval in seconds (optional, default: `5`).
      </ResponseField>

      <ResponseField name="read_your_writes" type="boolean">
        Boolean value indicating whether to read your writes (optional, default: `true`).
      </ResponseField>

      <ResponseField name="encryption_key" type="string">
        String value for encryption purposes (optional, default: empty).
      </ResponseField>
    </Expandable>
  </Step>

  <Step title="Project Structure Example">
    ```bash
    src/
    ├── helpers.php
    └── Todo.php
    vendor/
    composer.json
    composer.lock
    todo            # todo executable
    ```

    Here you simple php todo cli + Doctrine BDAL

    <CodeGroup>
      ```php todo
      #!/usr/bin/env php
      <?php

      use Turso\Todo\CLI\Todo;

      require_once __DIR__ . '/vendor/autoload.php';

      $header = 'TODO CLI + TURSO';

      echo $header . PHP_EOL;
      function main()
      {
          echo str_repeat('-', WIDTH - 18) . "  Todo CLI - " . VERSION . PHP_EOL;

          while (true) {
              echo "[L] List | [A] Add | [E] Edit | [D] Delete | [X] Exit" . PHP_EOL;
              echo "command: ";

              $choice = trim(fgets(STDIN));

              $app = new Todo();

              switch (strtolower($choice)) {
                  case 'l':
                      $app->listTodos();
                      break;
                  case 'a':
                      $app->addTodo();
                      clearScreen();
                      break;
                  case 'e':
                      $app->editTodo();
                      clearScreen();
                      break;
                  case 'd':
                      $app->deleteTodo();
                      clearScreen();
                      break;
                  case 'x':
                      exit("Goodbye!" . PHP_EOL);
                  default:
                      echo "Invalid choice." . PHP_EOL;
                      clearScreen();
              }
          }

          echo PHP_EOL;
      }

      main();
      ```

      ```php src/helpers.php
      <?php

      use Doctrine\DBAL\Connection;
      use Doctrine\DBAL\DriverManager;

      const WIDTH = 100;
      const VERSION = '1.0.0';

      function clearScreen()
      {
          if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
              system('cls');
          } else {
              system('clear');
          }
      }

      function createConnection(): Connection
      {
          $params = [
              "auth_token"        => getenv('TURSO_AUTH_TOKEN'),
              "sync_url"          => getenv('TURSO_DATABASE_URL'),
              'driverClass'       => \Turso\Doctrine\DBAL\Driver::class,
          ];

          $db = DriverManager::getConnection($params);
          
          return $db;
      }
      ```

      ```php src/Todo.php
      <?php

      namespace Turso\Todo\CLI;

      use Doctrine\DBAL\Connection;

      class Todo
      {

          private Connection $db;

          public function __construct()
          {
              $this->db = createConnection();
          }

          public function loadTodos(): array
          {
              $sql = "SELECT * FROM todos";
              return $this->db->fetchAllAssociative($sql);
          }

          public function saveTodo(string $todo): void
          {
              $sql = "INSERT INTO todos (name) VALUES (?)";
              $this->db->executeStatement($sql, [$todo]);
          }

          public function updateTodo(int $id, string $todo): void
          {
              $sql = "UPDATE todos SET name = ? WHERE id = ?";
              $this->db->executeStatement($sql, [$todo, $id]);
          }

          public function removeTodo(int $id): void
          {
              $sql = "DELETE FROM todos WHERE id = ?";
              $this->db->executeStatement($sql, [$id]);
          }

          public function listTodos()
          {
              $todos = $this->loadTodos();
              echo "\n" . "TODO-List   " . str_repeat('-', WIDTH - 12) . "\n\n";
              if (!empty($todos)) {
                  foreach ($todos as $todo) {
                      echo sprintf("[%d] %s\n", $todo['id'], $todo['name']);
                  }
              } else {
                  echo "Nothing...\n";
              }
              echo "\n" . str_repeat('-', WIDTH) . "\n";
          }

          public function addTodo()
          {
              echo "Enter the new To-Do: ";
              $todo = trim(fgets(STDIN));
              $this->saveTodo($todo);
              echo "To-Do added.\n";
          }

          public function editTodo()
          {
              $this->listTodos();
              echo "Enter the number of the To-Do to edit: ";
              $index = intval(trim(fgets(STDIN)));

              $findTodo = $this->db->executeQuery("SELECT * FROM todos WHERE id = ?", [$index])->fetchAssociative();

              if (!empty($findTodo)) {
                  echo "Enter the new value: ";
                  $todo = trim(fgets(STDIN));
                  $this->updateTodo($findTodo['id'], $todo);
                  echo "To-Do updated.\n";
              } else {
                  echo "Invalid index.\n";
              }
          }

          public function deleteTodo()
          {
              $this->listTodos();
              echo "Enter the number of the To-Do to delete: ";
              $index = intval(trim(fgets(STDIN)));
              $findTodo = $this->db->executeQuery("SELECT * FROM todos WHERE id = ?", [$index])->fetchAssociative();
              if (!empty($findTodo)) {
                  $this->removeTodo($findTodo['id']);
                  echo "To-Do deleted.\n";
              } else {
                  echo "Invalid index.\n";
              }
          }
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Your PHP Application Ready!">
    ![PHP TODO CLI - TURSO](https://i.imgur.com/dmrPFr2.png)
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="PHP Todo CLI + Doctrine DBAL" icon="github" href="https://github.com/tursodatabase/example/php-todo-cli-doctrine-dbal/tree/master">
    See the full source code
  </Card>

  <Card title="Symfony Rest API CRUD" icon="github" href="https://github.com/tursodatabase/example/symfony7-rest-api-crud/tree/master">
    See the full source code
  </Card>
</CardGroup>


# Turso Quickstart (PHP)

Get started with Turso and PHP using the libSQL client in a few simple steps.

In this PHP quickstart we will learn how to:

*   Install libSQL with Composer
*   Retrieve database credentials
*   Connect to a Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create
    one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install">
    Install the package to your project using composer:

    ```console
    composer require turso/libsql
    ```
  </Step>

  <Step title="Connect">
    Now connect to your local or remote database using the libSQL connector:

    <AccordionGroup>
      <Accordion title="Embedded Replica">
        ```php
        use Libsql\Database;

        $db = new Database(
            path: 'test.db',
            url: getenv('TURSO_URL'),
            authToken: getenv('TURSO_AUTH_TOKEN')
            syncIterval: 100 // Sync every second
        );
        $conn = $db->connect();
        ```
      </Accordion>

      <Accordion title="Local only">
        ```php
        use Libsql\Database;

        $db = new Database(path: "database.db");
        ```

        Or just:

        ```php
        use Libsql\Database;

        $db = new Database("database.db");
        ```
      </Accordion>

      <Accordion title="Local only">
        ```php
        use Libsql\Database;

        $db = new Database(path: "database.db");
        ```

        Or just:

        ```php
        use Libsql\Database;

        $db = new Database("database.db");
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```php
        use Libsql\Database;

        $db = new Database(
            url: getenv('TURSO_URL'),
            authToken: getenv('TURSO_AUTH_TOKEN'),
        )
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute SQL queries against your existing database as follows:

    ```php
    $createUsers = "
      CREATE TABLE IF NOT EXISTS users (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          name TEXT,
          age INTEGER
      );
      INSERT INTO users (name, age) VALUES ('Prof. Ir. Onno Widodo Purbo, M.Eng., Ph.D', 61);
      INSERT INTO users (name, age) VALUES ('Jim Geovedi', 41);
      INSERT INTO users (name, age) VALUES ('Nasirun', 59);
    ";

    $db->executeBatch($createUsers);
    $db->query("SELECT * FROM users")->fetchArray();
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```php Positional
      $db->query("SELECT * FROM users WHERE id = ?", [1])->fetchArray();
      ```

      ```php Named
      $db->query("SELECT * FROM users WHERE id = :id", [":id" => 1])->fetchArray();
      ```
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the database type
    to sync your local database with the primary database:

    ```php
    <?php

    $db->sync();
    ```
  </Step>
</Steps>


# Reference

libSQL PHP Reference

## Installing

Install the package to your project using composer:

```console
composer require turso/libsql
```

## Initializing

Make sure to add `use Libsql\Database` to access the `Database` object.

```php
$db = new Database("local.db")
```

## In-Memory Databases

libSQL supports connecting to [in-memory
databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't
require persistence:

```php
$db = new Database(":memory:");
```

Or the simpler:

```php
$db = new Database();
```

## Local Development

You can work locally by passing a path as the first parameter.

```php
$db = new Database("local.db")
```

Or more explicitly:

```php
$db = new Database(path: "local.db")
```

## Remote Only

You can use a remote only database by passing `url` and `authToken`.

```php
$db = new Database(
    url: getenv('TURSO_URL'),
    authToken: getenv('TURSO_AUTH_TOKEN'),
);
```

## Embedded Replicas

You can work with embedded replicas by passing a `path`, `url` and `authToken`.
Embedded replicas can sync from the remote URL and delegate writes to the
remote primary database:

```php
$db = new Database(
    path: 'test.db',
    url: getenv('TURSO_URL'),
    authToken: getenv('TURSO_AUTH_TOKEN'),
);
```

### Sync Interval

The `sync_interval` function allows you to set an interval for automatic synchronization of the database in the background:

```php
$db = new Database(
    path: 'test.db',
    url: getenv('TURSO_URL'),
    authToken: getenv('TURSO_AUTH_TOKEN'),
    syncInterval: 300, // Sync every 3 seconds
);
```

### Manual Sync

The `sync` function allows you to sync manually the local database with the
remote counterpart:

```php
$db->sync()
```

### Read Your Own Writes

The `readYourWrites` parameter configures the database connection to ensure
that writes are immediately visible to subsequent read operations initiated by
the same connection. This is **enabled by default**, and is particularly
important in distributed systems to ensure consistency from the perspective of
the writing process.

You can disable this behavior by passing `false`:

```php
$db = new Database(
    path: 'test.db',
    url: getenv('TURSO_URL'),
    authToken: getenv('TURSO_AUTH_TOKEN'),
    readYourWrites: false,
);
```

## Simple Query

You can acquire a connection from a database and call `query()` to invoke a
SQL statement, as well as optional arguments:

<CodeGroup>
  ```php Query
  $rows = $conn->query("SELECT * FROM users");
  ```

  ```php Arguments
  $rows = $conn->query("SELECT * FROM users WHERE id = ?1", [1]);
  ```

  ```php Named Arguments
  $rows = $conn->query("SELECT * FROM users WHERE id = :id", [":id" => 1]);
  ```
</CodeGroup>

## Prepared Statements

You can prepare a cached statement using `prepare()`, bind parameters, and then
query it:

```php
$stmt = $conn->prepare("SELECT * FROM users where id = ?");
$rows = $stmt->bind([1])->query();
```

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```rust Positional
  conn->query("SELECT * FROM users WHERE id = ?", [1]);
  ```

  ```rust Named
  conn->execute("INSERT INTO users (name) VALUES (:name)", [ ":name" => "Iku" ]);
  ```
</CodeGroup>

## Batch Transactions

A batch consists of multiple SQL statements executed sequentially within an
implicit transaction. The backend handles the transaction: success commits all
changes, while any failure results in a full rollback with no modifications.

```php
$conn->execute_batch("
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
  );

  INSERT INTO users (name) VALUES ('Alice');
  INSERT INTO users (name) VALUES ('Bob');
");
```

## Interactive Transactions

Interactive transactions in SQLite ensure the consistency of a series of read
and write operations within a transaction's scope. These transactions give you
control over when to commit or roll back changes, isolating them from other
client activity.

```php
$tx = conn->transaction();

$tx->execute("INSERT INTO users (name) VALUES (?1)", ["Iku"]);
$tx->execute("INSERT INTO users (name) VALUES (?1)", ["Iku 2"]);

tx->commit(); // or, $tx->rollback()
```


# Examples





# Flask + Turso

Set up Turso in your Flask project in minutes

![Flask banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/flask-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Flask app — [learn more](https://flask.palletsprojects.com/en/3.0.x/installation/#create-an-environment)

<Steps>
  <Step title="Install the libSQL dialect">
    ```bash
    pip install sqlalchemy-libsql python-dotenv
    ```
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Create database models">
    ```python models.py
    from sqlalchemy import String
    from sqlalchemy.orm import DeclarativeBase
    from sqlalchemy.orm import Mapped
    from sqlalchemy.orm import mapped_column

    class Base(DeclarativeBase):
        pass

    class Item(Base):
        __tablename__ = "items"
        id: Mapped[str] = mapped_column(primary_key=True)
        foo: Mapped[str] = mapped_column(String(255))
        bar: Mapped[str] = mapped_column(String(100))
        def __repr__(self) -> str:
            return f"Item(id={self.id!r}, foo={self.foo!r}, bar={self.bar!r})"
    ```
  </Step>

  <Step title="Query">
    ```python
    from dotenv import load_dotenv
    from sqlalchemy import create_engine
    from sqlalchemy.orm import Session
    from sqlalchemy import select
    from models import Item

    load_dotenv()

    # Get environment variables
    TURSO_DATABASE_URL = os.environ.get("TURSO_DATABASE_URL")
    TURSO_AUTH_TOKEN = os.environ.get("TURSO_AUTH_TOKEN")

    # construct special SQLAlchemy URL
    dbUrl = f"sqlite+{TURSO_DATABASE_URL}/?authToken={TURSO_AUTH_TOKEN}&secure=true"

    engine = create_engine(dbUrl, connect_args={'check_same_thread': False}, echo=True)

    @app.route("/", methods=(["GET"]))
    def home():
        session = Session(engine)

        # get & print items
        stmt = select(Item)

        for item in session.scalars(stmt):
            print(item)
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Social App" icon="github" href="https://github.com/turso-extended/app-find-me-on-python-htmx/tree/master">
    See the full source code
  </Card>
</CardGroup>


# SQLAlchemy + Turso

Configure SQLAlchemy to work with your Turso database

![SQLAlchemy Quickstart](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/sqlalchemy-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)

<Steps>
  <Step title="Install the libSQL dialect for SQLAlchemy">
    ```bash
    pip install sqlalchemy-libsql
    ```
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Create database models">
    ```python models.py
    from sqlalchemy import String
    from sqlalchemy.orm import DeclarativeBase
    from sqlalchemy.orm import Mapped
    from sqlalchemy.orm import mapped_column

    class Base(DeclarativeBase):
        pass

    class Foo(Base):
        __tablename__ = "foo"
        id: Mapped[str] = mapped_column(primary_key=True)
        bar: Mapped[str] = mapped_column(String(100))
        def __repr__(self) -> str:
            return f"Item(id={self.id!r}, bar={self.bar!r})"

    ```
  </Step>

  <Step title="Construct SQLAlchemy URL for Turso">
    ```py app.py
    from dotenv import load_dotenv
    from sqlalchemy import create_engine

    TURSO_DATABASE_URL = os.environ.get("TURSO_DATABASE_URL")
    TURSO_AUTH_TOKEN = os.environ.get("TURSO_AUTH_TOKEN")

    dbUrl = f"sqlite+{TURSO_DATABASE_URL}/?authToken={TURSO_AUTH_TOKEN}&secure=true"

    engine = create_engine(dbUrl, connect_args={'check_same_thread': False}, echo=True)
    ```
  </Step>

  <Step title="Query">
    ```py app.py
    from sqlalchemy.orm import Session
    from sqlalchemy import select
    from models import Foo

    @app.route("/", methods=(["GET"]))
    def home():
        session = Session(engine)

        # get & print foos
        stmt = select(Foo)

        for item in session.scalars(stmt):
            print(item)

    ```
  </Step>
</Steps>


# Turso Quickstart (Python)

Get started with Turso and Python using the libSQL client in a few simple steps.

In this Python quickstart we will learn how to:

*   Retrieve database credentials
*   Install the libSQL package
*   Connect to a Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install">
    First begin by adding libSQL to your project:

    ```bash
    pip install libsql-experimental
    ```
  </Step>

  <Step title="Connect">
    Then import the package:

    ```py
    import libsql_experimental as libsql
    ```

    Now connect to your local or remote database using the libSQL connector:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```py
        url = os.getenv("TURSO_DATABASE_URL")
        auth_token = os.getenv("TURSO_AUTH_TOKEN")

        conn = libsql.connect("hello.db", sync_url=url, auth_token=auth_token)
        conn.sync()
        ```
      </Accordion>

      <Accordion title="Local only">
        ```py
        conn = libsql.connect("hello.db")
        cur = conn.cursor()
        ```
      </Accordion>

      {/* <Accordion title="Remote only">
        ```py
        url = os.getenv("TURSO_DATABASE_URL")
        auth_token = os.getenv("TURSO_AUTH_TOKEN")

        conn = libsql.connect(database=url, auth_token=auth_token)
        ```

      </Accordion> */}
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute SQL queries against your existing database as follows:

    ```py
    conn.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER);")
    conn.execute("INSERT INTO users(id) VALUES (10);")

    print(conn.execute("select * from users").fetchall())
    ```
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the connector to sync your local database with the primary database.

    ```py
    conn.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER);")
    conn.execute("INSERT INTO users(id) VALUES (1);")
    conn.commit()

    conn.sync()

    print(conn.execute("select * from users").fetchall())
    ```
  </Step>
</Steps>


# Reference



## Embedded Replicas

You can work with [embedded replicas](/features/embedded-replicas) that can sync from the remote database to a local SQLite file, and delegate writes to the remote primary database:

```py
import os

import libsql_experimental as libsql

conn = libsql.connect("local.db", sync_url=os.getenv("LIBSQL_URL"),
                      auth_token=os.getenv("LIBSQL_AUTH_TOKEN"))
conn.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER);")
conn.execute("INSERT INTO users(id) VALUES (1);")
conn.commit()

print(conn.execute("select * from users").fetchall())
```

<Snippet file="embedded-replicas-warning.mdx" />

### Periodic Sync

You can automatically sync at intervals by passing time in seconds to the `sync_interval` option. For example, to sync every minute, you can use the following code:

```py
conn = libsql.connect("local.db", sync_interval=60, sync_url=os.getenv("LIBSQL_URL"),
                      auth_token=os.getenv("LIBSQL_AUTH_TOKEN"))
```

### Manual Sync

The `Sync` function allows you to sync manually the local database with the remote counterpart:

```py
conn.execute("INSERT INTO users(id) VALUES (2);")
conn.commit()
conn.sync()
```

## Encryption

To enable encryption on a SQLite file, pass the encryption secret to the `encryption_key` option:

```py
conn = libsql.connect("encrypted.db", sync_url=os.getenv("LIBSQL_URL"),
                      auth_token=os.getenv("LIBSQL_AUTH_TOKEN"),
                      encryption_key=os.getenv("ENCRYPTION_KEY"))
```

<Info>
  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](/libsql#encryption-at-rest).
</Info>


# Turso Examples (Ruby)



| Example                                                                                        | Description                                                                             |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| [local](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/local)               | Uses libsql with a local SQLite file. Creates database, inserts data, and queries.      |
| [remote](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/remote)             | Connects to a remote database. Requires environment variables for URL and auth token.   |
| [sync](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/sync)                 | Demonstrates synchronization between local and remote databases.                        |
| [transactions](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/transactions) | Shows transaction usage: starting, performing operations, and committing/rolling back.  |
| [memory](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/memory)             | Uses an in-memory SQLite database for temporary storage or fast access.                 |
| [vector](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/vector)             | Works with vector embeddings, storing and querying for similarity search.               |
| [encryption](https://github.com/tursodatabase/libsql-ruby/tree/master/examples/encryption)     | Creates and uses an encrypted SQLite database, demonstrating setup and data operations. |


# Turso Quickstart (Ruby)

Get started with Turso and Ruby using the libSQL client in a few simple steps.

<Snippet file="technical-preview-banner.mdx" />

In this Ruby quickstart we will learn how to:

*   Retrieve database credentials
*   Install the libSQL package
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Snippet file="mobile-secrets-warning.mdx" />
  </Step>

  <Step title="Install">
    Inside your Ruby project, install the following Rubygem:

    ```bash
    gem install turso_libsql
    ```
  </Step>

  <Step title="Connect">
    You must first initialize libSQL, create a `libsql_database_t` object, and then open a `libsql_connection_t` to it:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```rb
        require_relative 'turso_libsql'

        db =Libsql::Database.new(
          path: 'local.db',
          url: ENV['TURSO_DATABASE_URL'],
          auth_token: ENV['TURSO_AUTH_TOKEN'],
          sync_interval: 100
        )
        ```
      </Accordion>

      <Accordion title="Local only">
        ```rb
        require_relative 'turso_libsql'

        db = Libsql::Database.new(path: 'local.db')
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```rb
        require_relative 'turso_libsql'

        db = Libsql::Database.new(
          url: ENV['TURSO_DATABASE_URL'],
          auth_token: ENV['TURSO_AUTH_TOKEN']
        )
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database by preparing a statement and then executing it:

    ```c
    db.connect do |conn|
      rows = conn.query 'SELECT * FROM users'
      rows.close
    end
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```c Positional
      name = 'Iku'
      rows = conn.execute 'INSERT INTO users (id) VALUES (?)', [name]
      ```
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas, you should call `sync` on the database to sync your local database with the primary database, unless you are using `sync_interval` (though there is no issue with calling `sync` with `sync_interval` enabled):

    ```rb
    db.sync
    ```
  </Step>
</Steps>


# Examples





# Turso + Actix

Set up Turso in your Actix project in minutes

![Actix banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/actix-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Actix app — [learn more](https://actix.rs/docs/getting-started)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Add the libsql crate to the project">
    ```sh
    cargo add libsql
    ```

    <Note>
      Optionally, you can add a package such as [`dotenvy`](https://docs.rs/dotenvy/latest/dotenvy) to help you work with `.env` files:

      ```sh
      cargo add dotenvy
      ```
    </Note>
  </Step>

  <Step title="Execute SQL">
    ```rust
    #[tokio::main]
    #[actix_web::main]
    async fn main() -> std::io::Result<()> {
        HttpServer::new(|| App::new().route("/", web::get().to(index)).route("/items", web::get().to(get_items)))
            .bind(("127.0.0.1", 8080))?
            .run()
            .await
    }

    async fn get_items() -> Result<HttpResponse, Error> {
        dotenv().expect(".env file not found");

        let db_url = env::var("TURSO_DATABASE_URL").unwrap();
        let auth_token = env::var("TURSO_AUTH_TOKEN").unwrap();
        let db_file = env::var("LOCAL_DB").unwrap();

        let db = Builder::new_remote_replica(db_file, url, auth_token)
        .read_your_writes(true)
        .build()
        .await
        .unwrap();

        let conn = db.connect().unwrap();

        let mut results = conn.query("SELECT * FROM items", ()).await.unwrap();

        let mut items: Vec<T> = Vec::new();

        while let Some(row) = results.next().await.unwrap() {
            let item: Item = Item {
                task: row.get(0).unwrap(),
            };
            items.push(item);
        }

        Ok(HttpResponse::Ok().json(items))
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Turso + Actix Web Traffic Tracker" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-web-traffic-tracker-actix">
    See the full source code
  </Card>
</CardGroup>


# Turso + Axum

Set up Turso in your Axum project in minutes

![Axum banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/axum-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Axum app — [learn more](https://github.com/tokio-rs/axum)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Add the libsql crate to the project">
    ```sh
    cargo add libsql
    ```

    <Note>
      Optionally, you can add a package such as [`dotenvy`](https://docs.rs/dotenvy/latest/dotenvy) to help you work with `.env` files:

      ```sh
      cargo add dotenvy
      ```
    </Note>
  </Step>

  <Step title="Execute SQL">
    ```rust
    use libsql::{Builder, Connection, Database, Result};

    #[tokio::main]
    async fn main() -> Result<()> {
        dotenv().ok();

        let db_url = std::env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL must be set");
        let auth_token = std::env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN must be set");

        let db = Builder::new_remote(db_url, auth_token)
            .build()
            .await?;

        let conn = db.connect()?;

        // Execute a query
        let mut rows = conn.query("SELECT * FROM users", ()).await?;

        while let Some(row) = rows.next().await? {
            let id: i64 = row.get(0)?;
            let name: String = row.get(1)?;
            println!("User: {} - {}", id, name);
        }

        Ok(())
    }
    ```
  </Step>

  <Step title="Use in an Axum handler">
    ```rust
    use axum::{
        extract::State,
        routing::get,
        Json, Router,
    };
    use libsql::{Builder, Connection, Database};
    use serde::Serialize;

    #[derive(Clone)]
    struct AppState {
        db: Database,
    }

    #[derive(Serialize)]
    struct User {
        id: i64,
        name: String,
    }

    async fn get_users(State(state): State<AppState>) -> Json<Vec<User>> {
        let conn = state.db.connect().unwrap();
        let mut rows = conn.query("SELECT id, name FROM users", ()).await.unwrap();

        let mut users = Vec::new();
        while let Some(row) = rows.next().await.unwrap() {
            users.push(User {
                id: row.get(0).unwrap(),
                name: row.get(1).unwrap(),
            });
        }

        Json(users)
    }

    #[tokio::main]
    async fn main() {
        let db_url = std::env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL must be set");
        let auth_token = std::env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN must be set");

        let db = Builder::new_remote(db_url, auth_token)
            .build()
            .await
            .unwrap();

        let app_state = AppState { db };

        let app = Router::new()
            .route("/users", get(get_users))
            .with_state(app_state);

        axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
            .serve(app.into_make_service())
            .await
            .unwrap();
    }
    ```

    This example creates a shared `Database` instance in the application state, which is then used in the handler to execute queries.
  </Step>
</Steps>


# Turso + Rocket

Set up Turso in your Rocket project in minutes

![Rocket banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/rocket-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Rocket app — [learn more](https://rocket.rs/v0.5/guide/getting-started/)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Add the libsql crate to the project">
    ```sh
    cargo add libsql
    ```

    <Note>
      Optionally, you can add a package such as [`dotenvy`](https://docs.rs/dotenvy/latest/dotenvy) to help you work with `.env` files:

      ```sh
      cargo add dotenvy
      ```
    </Note>
  </Step>

  <Step title="Execute SQL">
    ```rust
    #[get("/todos")]
    async fn get_todos() -> Json<Vec<Todo>> {
        dotenv().expect(".env file not found");

        let url = env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL not found!");
        let token = env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN not found!");

        let db = Database::open_remote(url, token).unwrap();
        let conn = db.connect().unwrap();

        let mut response = conn.query("select * from todos", ()).await.unwrap();

        let mut todos: Vec<Todo> = Vec::new();
        while let Some(row) = response.next().unwrap() {
            let todo: Todo = Todo {
                task: row.get(0).unwrap(),
            };
            todos.push(todo);
        }

        Json(todos)
    }

    #[launch]
    fn rocket() -> _ {
        dotenv().ok();
        rocket::build().mount("/", routes![get_todos])
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Turso + Rocket Todo List" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-todo-rocket">
    See the full source code
  </Card>
</CardGroup>


# Tauri + Turso

Set up Turso in your Tauri project in minutes

![Tauri banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/tauri-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Tauri app — [learn more](https://tauri.app/v1/guides/getting-started/setup)

<Steps>
  <Step title="Add the following crates to the Tauri project's dependencies">
    ```toml src-tauri/Cargo.toml
    [dependencies]
    serde_json = "1.0"
    serde = { version = "1.0", features = ["derive"] }
    reqwest = { version = "0.11.22", features = ["json", "blocking"] }
    dotenvy = "0.15.7"
    tokio = { version = "1", features = ["full"] }
    libsql = { git = "https://github.com/tursodatabase/libsql" }
    tracing-subscriber = "0.3"
    tracing = "0.1.40"

    [patch.crates-io]
    sqlite3-parser = { git = "https://github.com/LucioFranco/lemon-rs" }
    ```
  </Step>

  <Step title="Fetch Rust dependencies inside the `src-tauri` directory.">
    ```bash
    cargo fetch
    ```
  </Step>

  <Step title="Configure database credentials">
    Get the database URL.

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token.

    ```bash
    turso db tokens create <database-name>
    ```

    Assign acquired credentials to the environment variables inside `src-tauri/.env`.

    ```bash src-tauri/.env
    TURSO_SYNC_URL="..."
    TURSO_AUTH_TOKEN="..."
    DB_PATH=./my-data.db # embedded replica
    ```
  </Step>

  <Step title="Execute SQL">
    ```rust src-tauri/src/main.rs
    use dotenvy::dotenv;
    use libsql::{params, Database};
    use serde::{Deserialize, Serialize};
    use std::env;

    use tracing::info;

    #[derive(Serialize, Debug)]
    struct Error {
        msg: String,
    }

    type Result<T> = std::result::Result<T, Error>;

    impl<T> From<T> for Error
    where
        T: std::error::Error,
    {
        fn from(value: T) -> Self {
            Self {
                msg: value.to_string(),
            }
        }
    }

    #[derive(Deserialize, Serialize, Debug)]
    pub struct Item {
        id: String,
        foo: String,
        bar: String,
    }

    #[tauri::command]
    async fn get_all_items() -> Result<Vec<Item>> {
        dotenv().expect(".env file not found");

        let db_path = env::var("DB_PATH").unwrap();
        let sync_url = env::var("TURSO_SYNC_URL").unwrap();
        let auth_token = env::var("TURSO_AUTH_TOKEN").unwrap();

        let db = Database::open_with_remote_sync(db_path, sync_url, auth_token).await?;

        let conn = db.connect()?;

        let mut results = conn
            .query("SELECT * FROM table_name", ())
            .await?;

        let mut items: Vec<Item> = Vec::new();
        while let Some(row) = results.next()? {
            let note: Item = Item {
                id: row.get(0)?,
                foo: row.get(1)?,
                bar: row.get(2)?,
            };
            items.push(item);
        }

        Ok(items)
    }

    fn main() {
        tracing_subscriber::fmt::init();

        tauri::Builder::default()
            .invoke_handler(tauri::generate_handler![
                get_all_items,
            ])
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Personal Notes App" icon="github" href="https://github.com/turso-extended/app-turso-notes/tree/master">
    See the full source code
  </Card>
</CardGroup>


# Turso Quickstart (Rust)

Get started with Turso and Rust using the libSQL crate in a few simple steps

In this Rust quickstart we will learn how to:

*   Retrieve database credentials
*   Install the Rust libSQL crate
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install">
    First begin by installing the `libsql` [crate](https://crates.io/crates/libsql):

    ```bash
    cargo add libsql
    ```
  </Step>

  <Step title="Connect">
    You must first create a `Database` object and then open a `Connection` to it:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```rust
        use libsql::Builder;

        let url = std::env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL must be set");
        let token = std::env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN must be set");

        let db = Builder::new_remote_replica("local.db", url, token)
            .build()
            .await?;
        let conn = db.connect()?;
        ```
      </Accordion>

      <Accordion title="Local only">
        ```rust
        use libsql::Builder;

        let db = Builder::new_local("local.db").build().await?;
        let conn = db.connect()?;
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```rust
        use libsql::Builder;

        let url = std::env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL must be set");
        let token = std::env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN must be set");

        let db = Builder::new_remote(url, token)
            .build()
            .await?;
        let conn = db.connect()?;
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database by calling `execute()`:

    ```rust
    conn.execute("SELECT * FROM users", ()).await?;
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```rust Positional
      conn.execute("SELECT * FROM users WHERE id = ?1", libsql::params![1]).await?;
      ```

      ```rust Named
      conn.execute("INSERT INTO users (name) VALUES (:name)", libsql::named_params! { ":name": "Iku" }).await?;
      ```
    </CodeGroup>

    To retrieve results from a query, you can use the `query()` method:

    ```rust
    let mut rows = conn.query("SELECT * FROM users", ()).await?;

    while let Some(row) = rows.next().await? {
        let id: i64 = row.get(0)?;
        let name: String = row.get(1)?;
        println!("User: {} - {}", id, name);
    }
    ```
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the database type to sync your local database with the primary database:

    ```rust
    db.sync().await.unwrap();
    ```

    You can also set up automatic periodic syncing when creating the database:

    ```rust
    use std::time::Duration;

    let db = Builder::new_remote_replica("local.db", url, token)
        .sync_interval(Duration::from_secs(60))
        .build()
        .await?;
    ```

    This will automatically sync the database every 60 seconds.
  </Step>
</Steps>


# Reference

libSQL Rust Reference

The libSQL Rust crate contains everything you need to work with Turso and works flawlessly with popular async runtimes like `tokio`.

## Installing

Install the crate in your project using the following command:

```bash
cargo add libsql
```

### Conditional compilation

The libsql rust client supports [conditionally compiling](https://doc.rust-lang.org/cargo/reference/features.html#dependency-features) certain features to reduce compile times depending on what features you would like to use.

The following features are available:

| Feature       | Description                                                                                                                                                                                                                                          |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `remote`      | Enables the HTTP-only client, allowing communication with a remote sqld server using pure Rust. Does not require compiling C code for SQLite. Suitable for projects that only need to interact with a remote database.                               |
| `core`        | Enables the local database only, incorporating the C SQLite3 code into the build. This is the foundation for local database operations but does not include additional features like replication or encryption.                                      |
| `replication` | Combines core with additional code required for replication, enabling the embedded replica features.                                                                                                                                                 |
| `encryption`  | Enables encryption at rest support, adding the necessary code to compile encryption capabilities and expose functions for configuring it. **This is optional and not enabled by default**, catering to projects that require enhanced data security. |

```toml
[dependencies]
libsql = { version = "...", features = ["encryption"] }
```

<Note>
  Using `core` and `replication` features require a c compiler. The `encryption` feature requires `cmake` to be installed on your system.
</Note>

## Initializing

Make sure add the crate to your project at the top of your file:

```rust
use libsql::Builder;

let url = env::var("LIBSQL_URL").expect("LIBSQL_URL must be set");
let token = env::var("LIBSQL_AUTH_TOKEN").unwrap_or_default();

let mut db = Builder::new_remote_replica("local.db", &url, &token).build().await.unwrap();
let conn = db.connect().unwrap();
```

## In-Memory Databases

libSQL supports connecting to [in-memory databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't require persistence:

```rust
use libsql::Builder;

let db = Builder::new_local(":memory:").build().await.unwrap();
let conn = db.connect().unwrap();
```

## Local Development

You can work locally using an SQLite file using `new_local`:

```rust
use libsql::Builder;

let mut db = Builder::new_local("local.db").build().await.unwrap();
let conn = db.connect().unwrap();
```

## Embedded Replicas

You can work with embedded replicas using `new_remote_replica` that can sync from the remote URL and delegate writes to the remote primary database:

```rust
use libsql::Builder;

let url = env::var("LIBSQL_URL").expect("LIBSQL_URL must be set");
let token = env::var("LIBSQL_AUTH_TOKEN").unwrap_or_default();

let mut db = Builder::new_remote_replica("local.db", &url, &token).build().await.unwrap();
let conn = db.connect().unwrap();
```

### Manual Sync

The `sync` function allows you to sync manually the local database with the remote counterpart:

```rust
use libsql::Builder;

let url = env::var("LIBSQL_URL").expect("LIBSQL_URL must be set");
let token = env::var("LIBSQL_AUTH_TOKEN").unwrap_or_default();

let mut db = Builder::new_remote_replica("local.db", &url, &token).build().await.unwrap();

let conn = db.connect().unwrap();

db.sync().await.unwrap(); // Call sync manually to update local database
```

<Info>
  If you require full control over how frames get from your instance of `sqld` (libSQL Server), you can do this using `new_local_replica` and `sync_frames`. Reach out to us [on Discord](https://discord.gg/turso) if you want to learn more.
</Info>

### Sync Interval

The `sync_interval` function allows you to set an interval for automatic synchronization of the database in the background:

```rust
use libsql::Builder;
use std::time::Duration;

let url = env::var("LIBSQL_URL").expect("LIBSQL_URL must be set");
let token = env::var("LIBSQL_AUTH_TOKEN").unwrap_or_default();

let mut db = Builder::new_remote_replica("local.db", &url, &token)
  .sync_interval(Duration::from_secs(300)) // Sync every 5 minutes
  .build()
  .await.unwrap();

let conn = db.connect().unwrap();
```

### Read Your Own Writes

The `read_your_writes` function configures the database connection to ensure that writes are immediately visible to subsequent read operations initiated by the same connection. This is **enabled by default**, and is particularly important in distributed systems to ensure consistency from the perspective of the writing process.

You can disable this behavior by passing `false` to the function:

```rust
use libsql::Builder;

let url = env::var("LIBSQL_URL").expect("LIBSQL_URL must be set");
let token = env::var("LIBSQL_AUTH_TOKEN").unwrap_or_default();

let mut db = Builder::new_remote_replica("local.db", &url, &token)
  .read_your_writes(false) // Disable reading your own writes
  .build()
  .await.unwrap();

let conn = db.connect().unwrap();
```

## Encryption

To enable encryption on a SQLite file (`new_local` or `new_remote_replica`), make sure you have the [`encryption` feature enabled](#conditional-compilation), and pass the `encryption_config`:

<Snippet file="encryption-at-rest-rust.mdx" />

<Info>
  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](/libsql#encryption-at-rest).
</Info>

## Simple query

You can pass a string to `execute()` to invoke a SQL statement, as well as optional arguments:

<CodeGroup>
  ```rust Query
  conn.execute("SELECT * FROM users", ()).await?;
  ```

  ```rust Arguments
  conn.execute("SELECT * FROM users WHERE id = ?1", [1]).await?;
  ```
</CodeGroup>

## Prepared Statements

You can prepare a cached statement using `prepare()` and then execute it with `query()`:

```rust
let stmt = db_conn.prepare("SELECT * FROM users").await?;

db_conn.query(&stmt, [&1]).await?;
```

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```rust Positional
  conn.execute("SELECT * FROM users WHERE id = ?1", params![1]).await?;
  ```

  ```rust Named
  conn.execute("INSERT INTO users (name) VALUES (:name)", libsql::named_params! { ":name": "Iku" }).await?;
  ```
</CodeGroup>

## Deserialization

You can use the `de::from_row` function to deserialize a row into a struct:

```rust
use libsql::{de, Builder};

let mut stmt = conn
  .prepare("SELECT * FROM users WHERE id = ?1")
  .await
  .unwrap();
let row = stmt
  .query([1])
  .await
  .unwrap()
  .next()
  .await
  .unwrap()
  .unwrap();

#[derive(Debug, serde::Deserialize)]
struct User {
  name: String,
  age: i64,
  vision: f64,
  avatar: Vec<u8>,
}

let user = de::from_row::<User>(&row).unwrap();
```

## Batch Transactions

A batch consists of multiple SQL statements executed sequentially within an implicit transaction. The backend handles the transaction: success commits all changes, while any failure results in a full rollback with no modifications.

```rust
conn.execute_batch(r#"
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
  );

  INSERT INTO users (name) VALUES ('Alice');
  INSERT INTO users (name) VALUES ('Bob');
"#).await?;
```

## Interactive Transactions

Interactive transactions in SQLite ensure the consistency of a series of read and write operations within a transaction's scope. These transactions give you control over when to commit or roll back changes, isolating them from other client activity.

*   `transaction()` — with default transaction behavior (`DEFFERED`)
*   `transaction_with_behavior()` — with custom transaction behavior

<CodeGroup>
  ```rust Default
  let mut tx = db_conn.transaction().await?;

  tx.execute("INSERT INTO users (name) VALUES (?1)", ["Iku"]).await?;
  tx.execute("INSERT INTO users (name) VALUES (?1)", ["Iku 2"]).await?;

  tx.commit().await?;
  ```

  ```rust Advanced control
  let mut tx = db_conn.transaction_with_behavior(TransactionBehavior::Immediate).await?;

  tx.execute("UPDATE users SET age = age + 1 WHERE id = ?1", [1]).await?;
  tx.execute("DELETE FROM users WHERE id = ?1", [2]).await?;

  if operations_successful {
    tx.commit().await?;
  } else {
    tx.rollback().await?;
  }
  ```
</CodeGroup>


# Turso Quickstart (Swift)

Get started with Turso and Swift using the libSQL client in a few simple steps.

<Snippet file="technical-preview-banner.mdx" />

In this Swift quickstart we will learn how to:

*   Retrieve database credentials
*   Install the libSQL package
*   Connect to a local or remote Turso database
*   Execute a query using SQL
*   Sync changes to local database (optional)

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Snippet file="mobile-secrets-warning.mdx" />
  </Step>

  <Step title="Install">
    First begin by adding `libsql` as a package dependency in XCode using this repo:

    <Card title="libSQL Swift" href="https://github.com/tursodatabase/libsql-swift">
      Build from source code
    </Card>

    Or add it to your SwiftPM dependencies:

    ```swift
    import PackageDescription

    let package = Package(
        // ...
        dependencies: [
            .package(url: "https://github.com/tursodatabase/libsql-swift", from: "0.1.1"),
        ],
        // ...
    )
    ```
  </Step>

  <Step title="Connect">
    You must first create a `Database` object and then open a `Connection` to it:

    <AccordionGroup>
      <Accordion title="Embedded Replicas">
        ```swift
        import Libsql

        let db = try Database(
            path: "./local.db",
            url: "TURSO_DATABASE_URL",
            authToken: "TURSO_AUTH_TOKEN",
            syncInterval: 300
        )

        let conn = try db.connect()
        ```
      </Accordion>

      <Accordion title="Local only">
        ```swift
        import Libsql

        let db = try Database(
            path: "./local.db",
        )

        let conn = try db.connect()
        ```
      </Accordion>

      <Accordion title="Remote only">
        ```swift
        import Libsql

        let db = try Database(
            url: "TURSO_DATABASE_URL",
            authToken: "TURSO_AUTH_TOKEN"
        )

        let conn = try db.connect()
        ```
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Execute">
    You can execute a SQL query against your existing database by calling `query()`,
    or `execute()` when you expect the query to not yield any rows:

    ```swift
    let rows = try conn.query("SELECT * FROM users")
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```swift Positional Query
      try conn.query("SELECT * FROM users WHERE id = ?", 1)
      ```

      ```swift Positional Insert
      try conn.execute("INSERT INTO users (id) VALUES (?)", 1)
      ```

      <Note>Named arguments are not supported yet.</Note>
    </CodeGroup>
  </Step>

  <Step title="Sync (Embedded Replicas only)">
    When using embedded replicas you should call `sync()` on the database type to
    sync your local database with the primary database, unless you are using
    `sync_interval` (though there is no issue with calling `sync` with
    `sync_interval` enabled):

    ```swift
    try db.sync()
    ```
  </Step>
</Steps>


# Swift Reference

libSQL Swift Reference

<Snippet file="technical-preview-banner.mdx" />

## Installing

First begin by adding `libsql` as a package dependency in XCode using this repo:

<Card title="libSQL Swift" href="https://github.com/tursodatabase/libsql-swift">
  Build from source code
</Card>

Or add it to your SwiftPM dependencies:

```swift
import PackageDescription

let package = Package(
    // ...
    dependencies: [
        .package(url: "https://github.com/tursodatabase/libsql-swift", from: "0.1.1"),
    ],
    // ...
)
```

## In-Memory Databases

libSQL supports connecting to [in-memory
databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't
require persistence:

```swift
import Libsql

let db = Database(":memory:")
let conn = try db.connect()
```

## Local Development

You can work locally using an SQLite file:

```swift
import Libsql

let db = Database("local.db")
let conn = try db.connect()
```

## Embedded Replicas

You can work with embedded replicas that can sync from the remote URL and
delegate writes to the remote primary database:

```swift
import Libsql

let db = try Database(
    path: "./local.db",
    url: "TURSO_DATABASE_URL",
    authToken: "TURSO_AUTH_TOKEN"
)

let conn = try db.connect()
```

### Manual Sync

The `sync` function allows you to sync manually the local database with the remote counterpart:

```swift
try db.sync() // Call sync manually to update local database
```

### Sync Interval

The `syncInterval` parameter allows you to set an interval for automatic
synchronization of the database in the background:

```swift
import Libsql

let db = try Database(
    path: "./local.db",
    url: "TURSO_DATABASE_URL",
    authToken: "TURSO_AUTH_TOKEN"
    syncInterval: 300 // Sync every 3 seconds
)

let conn = try db.connect()
```

### Read Your Own Writes

The `readYourWrites` parameter configures the database connection to ensure
that writes are immediately visible to subsequent read operations initiated by
the same connection. This is **enabled by default**, and is particularly
important in distributed systems to ensure consistency from the perspective of
the writing process.

You can disable this behavior by passing `false` to the function:

```swift
import Libsql

let db = try Database(
    path: "./local.db",
    url: <LIBSQL_URL>,
    authToken: <LIBSQL_AUTH_TOKEN>,
    readYourWrites: false
)

let conn = try db.connect()
```

## Simple query

You can pass a string to `query()` to invoke a SQL statement, as well as
optional arguments:

<CodeGroup>
  ```swift Execute
  try conn.execute("INSERT INTO users VALUES (?)", [1])
  ```

  ```swift Query
  try conn.query("SELECT * FROM users")
  ```

  ```swift Arguments
  try conn.query("SELECT * FROM users WHERE id = ?", [1])
  ```
</CodeGroup>

## Prepared Statements

You can prepare a cached statement using `prepare()` and then execute it with
`query()`:

```swift
let stmt = try conn.prepare("SELECT * FROM users WHERE id = ?")
stmt.bind([1])
stmt.query()
```

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```swift Positional
  try conn.query("SELECT * FROM users WHERE id = ?", [1])
  ```

  ```swift Named
  try conn.query("SELECT * FROM users WHERE id = :id", [ ":id": 1 ])
  ```
</CodeGroup>


# Examples





# Astro + Turso

Set up Turso in your Astro project in minutes.

![Astro banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/astro-banner.png)

## Prerequisites

To get the most out of this guide, you'll need to:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Astro project — [learn more](https://docs.astro.build/en/install/auto/#1-run-the-setup-wizard)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL client">
    ```ts src/turso.ts
    import { createClient } from "@libsql/client/web";

    export const turso = createClient({
      url: import.meta.env.TURSO_DATABASE_URL!,
      authToken: import.meta.env.TURSO_AUTH_TOKEN,
    });
    ```

    <Note>
      Astro will soon introduce a new ENV API. [Take a
      look](https://docs.astro.build/en/reference/configuration-reference/#experimentalenv).
    </Note>
  </Step>

  <Step title="Execute SQL">
    ```ts
    ---
    import { turso } from './turso'

    const { rows } = await turso.execute('SELECT * FROM table_name')
    ---
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Blog" icon="github" href="https://github.com/turso-extended/app-tustro-blog">
    See the full source code
  </Card>
</CardGroup>


# Elysia + Turso

Set up Turso in your Elysia project in minutes.

![Elysia banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/elysia-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have an Elysia app — [learn more](https://elysiajs.com/quick-start.html)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL client">
    <Snippet file="configure-libsql-client-ts.mdx" />
  </Step>

  <Step title="Execute SQL">
    ```ts
    import { Elysia } from "elysia";
    import { turso } from "./lib/turso";

    const app = new Elysia().get("/items", async () => {
      const { rows } = await turso.execute("SELECT * FROM items");
      return rows;
    });
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Expenses tracker app with Elysia & Turso" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-expenses-tracker-elysia">
    See the full source code
  </Card>
</CardGroup>


# Hono + Turso

Set up Turso in your Hono project in minutes.

![Hono banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/hono-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Hono app — [learn more](https://hono.dev/top#quick-start)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL client">
    <Snippet file="configure-libsql-client-ts.mdx" />
  </Step>

  <Step title="Execute SQL">
    ```ts
    import { Hono } from "hono";
    import { turso } from "./lib/turso";

    const app = new Hono();

    app.get("/items", async (c) => {
      const { rows } = await turso.execute("SELECT * FROM items");

      return c.json({ rows });
    });
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Expenses tracker app with Hono & Turso" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-expenses-tracker-hono">
    See the full source code
  </Card>
</CardGroup>


# Next.js + Turso

Set up Turso in your Next.js project in minutes.

![Next.js banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/nextjs-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Next.js app — [learn more](https://nextjs.org/docs/getting-started/installation)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL client">
    <Snippet file="configure-libsql-client-ts.mdx" />
  </Step>

  <Step title="Execute SQL">
    <CodeGroup>
      ```tsx App Router
      import { turso } from "@/lib/turso";

      export default async function Page() {
        const { rows } = await turso.execute("SELECT * FROM table_name");

        return (
          <ul>
            {rows.map((row) => (
              <li key={row.id}>{row.id}</li>
            ))}
          </ul>
        );
      }
      ```

      ```ts Pages Directory
      import type { InferGetServerSidePropsType, GetServerSideProps } from "next";

      import { turso } from "@/lib/turso";

      export const getServerSideProps = (async () => {
        const { rows } = await turso.execute("SELECT * FROM table_name");

        return {
          props: {
            rows,
          },
        };
      }) satisfies GetServerSideProps<{ rows: any[] }>;

      export default function Page({
        rows,
      }: InferGetServerSidePropsType<typeof getServerSideProps>) {
        return (
          <ul>
            {rows.map((row) => (
              <li key={row.id}>{row.id}</li>
            ))}
          </ul>
        );
      }
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Full Stack App" icon="github" href="https://github.com/turso-extended/app-turso-nextjs-starter">
    See the full source code
  </Card>
</CardGroup>


# Nuxt + Turso

Set up Turso in your Nuxt project in minutes

![Nuxt banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/nuxt-banner.png)

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Nuxt app — [learn more](https://nuxt.com/docs/getting-started/installation#new-project)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    Get the database URL:

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token:

    ```bash
    turso db tokens create <database-name>
    ```

    Assign credentials to the environment variables inside `.env`.

    ```bash
    NUXT_TURSO_DATABASE_URL=
    NUXT_TURSO_AUTH_TOKEN=
    ```
  </Step>

  <Step title="Configure variables inside Nuxt's runtime config.">
    ```ts nuxt.config.ts
    export default defineNuxtConfig({
      runtimeConfig: {
        turso: {
          databaseUrl: "",
          authToken: "",
        },
      },
    });
    ```

    <Note>
      Make sure that names of the keys in the `runtimeConfig` object match the names
      of your environment variables. Read more about this
      [here](https://nuxt.com/docs/guide/going-further/runtime-config).
    </Note>
  </Step>

  <Step title="Configure libSQL Client.">
    ```ts server/utils/turso.ts
    import { createClient } from "@libsql/client";
    // You can optionally pass in the event to useRuntimeConfig
    // import { H3Event } from "h3";

    export function useTurso(/* event: H3Event */) {
      const { turso } = useRuntimeConfig(/* event */);

      return createClient({
        url: turso.databaseUrl,
        authToken: turso.authToken,
      });
    }
    ```
  </Step>

  <Step title="Execute SQL">
    ```ts server/api/items.get.ts
    export default defineEventHandler(async (event) => {
      const client = useTurso(/* event */);
      const { rows } = await client.execute("select * from table_name");

      return {
        data: {
          items: rows,
        },
      };
    });
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Website + App" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-top-web-frameworks">
    See the full source code
  </Card>
</CardGroup>


# Quasar + Turso

Set up Turso in your Quasar project in minutes

![Quasar banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/quasar-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Quasar app — [learn more](https://quasar.dev/start/quick-start#step-1-create-a-project)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    Get the database URL:

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token:

    ```bash
    turso db tokens create <database-name>
    ```

    Assign credentials to the environment variables inside `.env.local`.

    ```bash
    VITE_TURSO_DATABASE_URL="..."
    VITE_TURSO_AUTH_TOKEN="..."
    ```
  </Step>

  <Step title="Configure libSQL Client">
    ```js
    import { createClient } from "@libsql/client/web";

    const turso = createClient({
      url: import.meta.env.VITE_TURSO_DATABASE_URL,
      authToken: import.meta.env.VITE_TURSO_AUTH_TOKEN,
    });
    ```

    <Info>
      Avoid a [gotcha
      moment](https://github.com/quasarframework/quasar/discussions/16071) by
      modifying the app configuration using the settings below.
    </Info>

    ```javascript quasar.config.js
    {
      build: {
        target: {
          browser: [
            'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13.1'
          ],
          node: 'node16'
        },
        extendViteConf(config) {
          config.optimizeDeps = {
            esbuildOptions: {
              target: 'es2020',
            }
          }
        }
      }
    }
    ```
  </Step>

  <Step title="Fetch data from Turso.">
    ```js IndexPage.vue
    import { ref } from "vue";

    const items = ref();

    const { rows } = await turso.execute("select * from my-table");

    items.value = rows;
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Todo App" icon="github" href="https://github.com/tursodatabase/examples/tree/master/quasar-todo-list">
    See the full source code
  </Card>
</CardGroup>


# Qwik + Turso

Set up Turso in your Qwik project in minutes

![Qwik banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/qwik-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Qwik app — [learn more](https://qwik.builder.io/docs/getting-started/#create-an-app-using-the-cli)

<Steps>
  <Step title="Add Turso Integration">
    <CodeGroup>
      ```bash npm
      npm run qwik add turso
      ```

      ```bash pnpm
      pnpm qwik add turso
      ```

      ```bash yarn
      yarn qwik add turso
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure database credentials">
    Get the database URL:

    ```bash
    turso db show --url <database-name>
    ```

    Get the database authentication token:

    ```bash
    turso db tokens create <database-name>
    ```

    Assign credentials to the environment variables inside `.env.local`.

    ```bash
    PRIVATE_TURSO_DATABASE_URL="..."
    PRIVATE_TURSO_AUTH_TOKEN="..."
    ```
  </Step>

  <Step title="Execute SQL">
    ```ts
    import { tursoClient } from "~/utils/turso";

    export const useFrameworks = routeLoader$(
      async (requestEvent: RequestEventBase) => {
        const db = tursoClient(requestEvent["env"]);
        const { rows } = await db.execute("select * from table_name");

        return {
          items: rows,
        };
      }
    );
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Social Website" icon="github" href="https://github.com/turso-extended/app-find-me-on">
    See the full source code
  </Card>

  <Card title="Shopping Cart" icon="github" href="https://github.com/turso-extended/app-turqw-store">
    See the full source code
  </Card>
</CardGroup>


# Remix + Turso

Set up Turso in your Remix project in minutes

![Remix banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/remix-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a Remix app — [learn more](https://remix.run/docs/en/main/start/quickstart#quick-start)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL Client.">
    <Snippet file="configure-libsql-client-ts.mdx" />
  </Step>

  <Step title="Execute SQL">
    ```ts app/routes/_index.ts
    import type { LoaderFunction } from "@remix-run/node";

    import { turso } from "~/lib/turso";

    export const loader: LoaderFunction = async () => {
      const { rows } = await turso.execute("SELECT * from TABLE_NAME");

      return {
        items: rows,
      };
    };
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="E-commerce Store" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-the-mug-store">
    See the full source code
  </Card>

  <Card title="CRM App" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-turso-crm">
    See the full source code
  </Card>
</CardGroup>


# SvelteKit + Turso

Set up Turso in your SvelteKit project in minutes

![SvelteKit banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/svelte-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Have a SvelteKit app — [learn more](https://kit.svelte.dev/docs/creating-a-project)

<Steps>
  <Step title="Install the libSQL SDK">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Configure database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Configure libSQL Client.">
    <CodeGroup>
      ```ts Node.js / Serverless
      import { TURSO_DATABASE_URL, TURSO_AUTH_TOKEN } from "$env/static/private";
      import { createClient } from "@libsql/client";

      export const turso = createClient({
        url: TURSO_DATABASE_URL,
        authToken: TURSO_AUTH_TOKEN,
      });
      ```

      ```ts Edge Runtimes
      import { TURSO_DATABASE_URL, TURSO_AUTH_TOKEN } from "$env/static/private";
      import { createClient } from "@libsql/client/web";

      export const turso = createClient({
        url: TURSO_DATABASE_URL,
        authToken: TURSO_AUTH_TOKEN,
      });
      ```
    </CodeGroup>
  </Step>

  <Step title="Execute SQL">
    <CodeGroup>
      ```ts src/routes/+page.server.ts
      import { turso } from "$lib/turso.server";

      export async function load() {
        const { rows } = await turso.execute("SELECT * FROM table_name");

        return { rows };
      }
      ```

      ```svelte src/routes/+page.svelte
      <script lang="ts">
        export let data
      </script>

      <ul>
        {#each data.rows as row}
          <li>{row.id}</li>
        {/each}
      </ul>
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Blog" icon="github" href="https://github.com/tursodatabase/examples/tree/master/app-at-the-polls">
    See the full source code
  </Card>
</CardGroup>


# Sentry

Trace slow queries and capture SQL errors with Sentry.

The [Sentry](https://sentry.io/integrations/turso) integration for `@libsql/client` provides tracing, breadcrumbs, and error handling for SQL queries.

<Snippet file="technical-preview-banner.mdx" />

## Install

```bash
npm install sentry-integration-libsql-client
```

## Quickstart

Once you have a `@libsql/client` instance, you can integrate it with Sentry like this:

```ts
import * as Sentry from "@sentry/node";
import { createClient } from "@libsql/client";
import { libsqlIntegration } from "sentry-integration-libsql-client";

const libsqlClient = createClient({
  url: "libsql://...",
  authToken: "...",
});

Sentry.init({
  dsn: "...",
  integrations: [libsqlIntegration(libsqlClient, Sentry)],
});

await libsqlClient.execute("SELECT * FROM users");
```

## Options

By default, everything is turned on. You can configure what you want by passing a third argument to the `libsqlIntegration` function.

| Option        | Default | Description                            |
| ------------- | ------- | -------------------------------------- |
| `tracing`     | `true`  | Enable tracing for SQL queries.        |
| `breadcrumbs` | `true`  | Enable breadcrumbs for SQL queries.    |
| `errors`      | `true`  | Enable error handling for SQL queries. |

```ts
Sentry.init({
  dsn: "...",
  integrations: [
    libsqlIntegration(libsqlClient, Sentry, {
      tracing: false,
      breadcrumbs: false,
      errors: false,
    }),
  ],
});
```


# Drizzle + Turso

Configure Drizzle to work with Turso

![Drizzle banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/drizzle-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)

<Steps>
  <Step title="Install Drizzle and the libSQL SDK">
    <CodeGroup>
      ```bash npm
      npm i drizzle-orm @libsql/client dotenv
      npm i -D drizzle-kit
      ```

      ```bash pnpm
      pnpm add drizzle-orm @libsql/client dotenv
      pnpm add -D drizzle-kit
      ```

      ```bash yarn
      yarn add drizzle-orm @libsql/client dotenv
      yarn add -D drizzle-kit
      ```
    </CodeGroup>

    Finish by updating `package.json` to include three new `scripts`:

    ```json
    {
      "scripts": {
        "db:generate": "drizzle-kit generate",
        "db:migrate": "drizzle-kit migrate",
        "db:studio": "drizzle-kit studio"
      }
    }
    ```
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Create a Drizzle schema">
    ```ts db/schema.ts
    import { sql } from "drizzle-orm";
    import { text, sqliteTable } from "drizzle-orm/sqlite-core";

    export const fooTable = sqliteTable("foo", {
      bar: text("bar").notNull().default("Hey!"),
    });
    ```
  </Step>

  <Step title="Configure Drizzle Kit">
    Create the file `drizzle.config.ts` in the root of your project with the following:

    ```ts drizzle.config.ts
    require("dotenv").config();

    import type { Config } from "drizzle-kit";

    export default {
      schema: "./db/schema.ts",
      out: "./migrations",
      dialect: "turso",
      dbCredentials: {
        url: process.env.TURSO_DATABASE_URL!,
        authToken: process.env.TURSO_AUTH_TOKEN,
      },
    } satisfies Config;
    ```

    <Note>
      We're using `dotenv` above, but if you're using something like Next.js, Remix, Astro, or Vite, you can use their built-in environment variables manager to source these values.
    </Note>
  </Step>

  <Step title="Connect Drizzle with libSQL">
    <CodeGroup>
      ```ts Node.js / Serverless
      import { drizzle } from "drizzle-orm/libsql";
      import { createClient } from "@libsql/client";

      const turso = createClient({
        url: process.env.TURSO_DATABASE_URL!,
        authToken: process.env.TURSO_AUTH_TOKEN,
      });

      export const db = drizzle(turso);
      ```

      ```ts Edge Runtimes
      import { drizzle } from "drizzle-orm/libsql";
      import { createClient } from "@libsql/client/web";

      const turso = createClient({
        url: process.env.TURSO_DATABASE_URL!,
        authToken: process.env.TURSO_AUTH_TOKEN,
      });

      export const db = drizzle(turso);
      ```
    </CodeGroup>
  </Step>

  <Step title="Database migrations">
    Drizzle can generate and apply database migrations with `drizzle-kit`.

    Whenever you make changes to the schema, run `db:generate`:

    ```bash
    npm run db:generate
    ```

    Now apply these changes to the database with `db:migrate`:

    ```bash
    npm run db:migrate
    ```
  </Step>

  <Step title="Query">
    ```ts
    import { db } from "./db";
    import { fooTable } from "./schema";

    const result = await db.select().from(fooTable).all();
    ```
  </Step>

  <Step title="Connect Drizzle Studio">
    <CodeGroup>
      ```bash npm
      npm run db:studio
      ```

      ```bash pnpm
      pnpm run db:studio
      ```
    </CodeGroup>
  </Step>
</Steps>

## Vector Embeddings

You can extend Drizzle to support Turso's native vector — [learn more](/features/ai-and-embeddings).

<Steps>
  <Step title="Define custom vector type">
    Inside `db/schema.ts`, add the following:

    ```typescript
    import { sql } from "drizzle-orm";
    import { customType } from "drizzle-orm/sqlite-core";

    const float32Array = customType<{
      data: number[];
      config: { dimensions: number };
      configRequired: true;
      driverData: Buffer;
    }>({
      dataType(config) {
        return `F32_BLOB(${config.dimensions})`;
      },
      fromDriver(value: Buffer) {
        return Array.from(new Float32Array(value.buffer));
      },
      toDriver(value: number[]) {
        return sql`vector32(${JSON.stringify(value)})`;
      },
    });
    ```
  </Step>

  <Step title="Create a table with a vector column">
    Now where you define the schema, invoke `float32Array` to create a column that stores vectors:

    ```typescript
    import { sqliteTable, integer } from "drizzle-orm/sqlite-core";

    export const vectorTable = sqliteTable("vector_table", {
      id: integer("id").primaryKey(),
      vector: float32Array("vector", { dimensions: 3 }),
    });
    ```
  </Step>

  <Step title="Create a vector index">
    You will need to use raw SQL to create the index:

    ```typescript
    import { drizzle } from "drizzle-orm/libsql";
    import { createClient } from "@libsql/client";

    const client = createClient({
      url: process.env.TURSO_DATABASE_URL!,
      authToken: process.env.TURSO_AUTH_TOKEN,
    });

    const db = drizzle(client);

    await db.run(sql`
      CREATE INDEX IF NOT EXISTS vector_index
      ON vector_table(vector)
      USING vector_cosine(3)
    `);
    ```
  </Step>

  <Step title="Insert vector data">
    ```typescript
    await db
      .insert(vectorTable)
      .values([{ vector: sql`vector32(${JSON.stringify([1.1, 2.2, 3.3])})` }]);
    ```
  </Step>

  <Step title="Query vector data">
    Calculate vector distance:

    ```typescript
    const res = await db
      .select({
        distance: sql<number>`vector_distance_cos(${vectorTable.vector}, vector32(${JSON.stringify([2.2, 3.3, 4.4])}))`,
      })
      .from(vectorTable);

    console.log(res);
    ```

    Perform efficient nearest neighbor search:

    ```typescript
    const topK = await db
      .select({
        id: sql`id`,
        distance: sql`distance`,
      })
      .from(
        sql`vector_top_k('vector_index', vector32(${JSON.stringify([2.2, 3.3, 4.4])}), 5)`,
      )
      .leftJoin(vectorTable, sql`${vectorTable}.id = id`);

    console.log(topK);
    ```
  </Step>
</Steps>

Remember to create appropriate indexes for efficient vector operations and adjust vector dimensions as needed for your use case.


# Prisma + Turso

Configure Prisma to work with your Turso database

![Prisma banner](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/guides/prisma-banner.png)

## Prerequisites

Before you start, make sure you:

*   [Install the Turso CLI](/cli/installation)
*   [Sign up or login to Turso](/cli/authentication#signup)
*   Prisma versions 5.4.2 and later

<Steps>
  <Step title="Install the libSQL SDK and its Prisma driver">
    <CodeGroup>
      ```bash npm
      npm install @libsql/client @prisma/adapter-libsql
      ```

      ```bash pnpm
      pnpm add @libsql/client @prisma/adapter-libsql
      ```

      ```bash yarn
      yarn add @libsql/client @prisma/adapter-libsql
      ```
    </CodeGroup>
  </Step>

  <Step title="Retrieve database credentials">
    <Snippet file="retrieve-database-credentials.mdx" />
  </Step>

  <Step title="Enable the `driverAdapters` preview feature flag:">
    ```js prisma/schema.prisma
    generator client {
      provider        = "prisma-client-js"
      previewFeatures = ["driverAdapters"]
    }
    ```
  </Step>

  <Step title="Generate Prisma client">
    <CodeGroup>
      ```sh npm
      npx prisma generate
      ```

      ```sh pnpm
      pnpm dlx prisma generate
      ```
    </CodeGroup>
  </Step>

  <Step title="Update your Prisma Client Instance">
    <CodeGroup>
      ```ts Node.js / Serverless
      import { PrismaClient } from "@prisma/client";
      import { PrismaLibSQL } from "@prisma/adapter-libsql";
      import { createClient } from "@libsql/client";

      const libsql = createClient({
        url: process.env.TURSO_DATABASE_URL,
        authToken: process.env.TURSO_AUTH_TOKEN,
      });

      const adapter = new PrismaLibSQL(libsql);
      const prisma = new PrismaClient({ adapter });
      ```

      ```ts Edge Runtimes
      import { PrismaClient } from "@prisma/client";
      import { PrismaLibSQL } from "@prisma/adapter-libsql";
      import { createClient } from "@libsql/client/web";

      const libsql = createClient({
        url: process.env.TURSO_DATABASE_URL,
        authToken: process.env.TURSO_AUTH_TOKEN,
      });

      const adapter = new PrismaLibSQL(libsql);
      const prisma = new PrismaClient({ adapter });
      ```
    </CodeGroup>
  </Step>

  <Step title="Query">
    ```ts
    const response = await prisma.table_name.findMany();
    ```
  </Step>
</Steps>


# Turso Quickstart (TypeScript / JS)

Get started with Turso and TypeScript using the libSQL client in a few simple steps

In this JavaScript quickstart we will learn how to:

*   Retrieve database credentials
*   Install the JavaScript libSQL client
*   Connect to a remote Turso database
*   Execute a query using SQL

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/quickstart).

    <Snippet file="retrieve-database-credentials.mdx" />

    <Info>You will want to store these as environment variables.</Info>
  </Step>

  <Step title="Install @libsql/client">
    <Snippet file="install-libsql-client-ts.mdx" />
  </Step>

  <Step title="Initialize a new client">
    Next add your database URL and auth token:

    <Snippet file="configure-libsql-client-ts.mdx" />
  </Step>

  <Step title="Execute a query using SQL">
    You can execute a SQL query against your existing database by calling `execute()`:

    ```ts
    await turso.execute("SELECT * FROM users");
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```ts Positional
      await turso.execute({
        sql: "SELECT * FROM users WHERE id = ?",
        args: [1],
      });
      ```

      ```ts Named
      await turso.execute({
        sql: "INSERT INTO users VALUES (:name)",
        args: { name: "Iku" },
      });
      ```
    </CodeGroup>
  </Step>
</Steps>


# Reference

libSQL JavaScript and TypeScript Reference

The following runtime environments are known to be compatible:

*   Node.js version 12 or later
*   Deno
*   CloudFlare Workers
*   Netlify & Vercel Edge Functions

<Info>
  The JavaScript SDK comes with TypeScript bindings and supports environments where either language can be used. Both ESM and CJS modules are provided.
</Info>

## Installing

<Snippet file="install-libsql-client-ts.mdx" />

## Initializing

Import `createClient` to initialize a client that you can use to query your database:

<Snippet file="configure-libsql-client-ts.mdx" />

<br />

<Info>
  If you're using libsql locally or an sqlite file, you can ignore passing `authToken`.
</Info>

## In-Memory Databases

libSQL supports connecting to [in-memory databases](https://www.sqlite.org/inmemorydb.html) for cases where you don't require persistence:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: ":memory:",
});
```

## Local Development

You can work locally using an SQLite file and passing the path to `createClient`:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: "file:path/to/db-file.db",
  authToken: "...",
});
```

<Warning>
  The `@libsql/client/web` does not support local file URLs.
</Warning>

## Embedded Replicas

You can work with embedded replicas by passing your Turso Database URL to `syncUrl`:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: "file:path/to/db-file.db",
  syncUrl: "libsql://[databaseName]-[organizationName].turso.io",
  authToken: "...",
});
```

<Snippet file="embedded-replicas-warning.mdx" />

### Manual Sync

The `sync()` function allows you to sync manually the local database with the remote counterpart:

```ts
await client.sync();
```

### Periodic Sync

You can automatically sync at intervals by configuring the `syncInterval` (seconds) property when instantiating a new libSQL client:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: "file:path/to/db-file.db",
  syncUrl: "libsql://[databaseName]-[organizationName].turso.io",
  syncInterval: 60,
  authToken: "...",
});
```

## Encryption

To enable encryption on a SQLite file, pass the `encryptionKey`:

<Snippet file="encryption-at-rest-typescript.mdx" />

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](/libsql#encryption-at-rest).

## Response

Each method listed below returns a `Promise<ResultSet>`:

| Property          | Type                          | Description                                                                                                        |
| ----------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `rows`            | `Array<Row>`                  | An array of Row objects containing the row values, empty for write operations                                      |
| `columns`         | `Array<string>`               | An array of strings with the names of the columns in the order they appear in each Row, empty for write operations |
| `rowsAffected`    | `number`                      | The number of rows affected by a write statement, `0` otherwise                                                    |
| `lastInsertRowid` | `bigint         \| undefined` | The ID of a newly inserted row, or `undefined` if there is none for the statement                                  |

## Simple query

You can pass a string or object to `execute()` to invoke a SQL statement:

<CodeGroup>
  ```ts String
  const result = await client.execute("SELECT * FROM users");
  ```

  ```ts Object
  const result = await client.execute({
    sql: "SELECT * FROM users WHERE id = ?",
    args: [1],
  });
  ```
</CodeGroup>

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```ts Positional
  const result = await client.execute({
    sql: "SELECT * FROM users WHERE id = ?",
    args: [1],
  });

  const result = await client.batch(
    [
      {
        sql: "INSERT INTO users VALUES (?)",
        args: ["Iku"],
      },
    ],
    "write"
  );
  ```

  ```ts Named
  const result = await client.execute({
    sql: "INSERT INTO users VALUES (:name)",
    args: { name: "Iku" },
  });

  const result = await client.batch(
    [
      {
        sql: "INSERT INTO users VALUES (:name)",
        args: { name: "Iku" },
      },
    ],
    "write"
  );
  ```
</CodeGroup>

<br />

<Info>
  libSQL supports the same named placeholder characters as SQLite — `:`, `@` and `$`.
</Info>

## Transaction Modes

| Mode       | SQLite command               | Description                                                                                                                                                                                        |
| ---------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `write`    | `BEGIN IMMEDIATE`            | The transaction may execute statements that read and write data. Write transactions executed on a replica are forwarded to the primary instance, and can't operate in parallel.                    |
| `read`     | `BEGIN TRANSACTION READONLY` | The transaction may only execute statements that read data (select). Read transactions can occur on replicas, and can operate in parallel with other read transactions.                            |
| `deferred` | `BEGIN DEFERRED`             | The transaction starts in read mode, then changes to write as soon as a write statement is executed. This mode change may fail if there is a write transaction currently executing on the primary. |

## Batch Transactions

A batch consists of multiple SQL statements executed sequentially within an implicit transaction. The backend handles the transaction: success commits all changes, while any failure results in a full rollback with no modifications.

```ts
const result = await client.batch(
  [
    {
      sql: "INSERT INTO users VALUES (?)",
      args: ["Iku"],
    },
    {
      sql: "INSERT INTO users VALUES (?)",
      args: ["Iku 2"],
    },
  ],
  "write"
);
```

## Interactive Transactions

Interactive transactions in SQLite ensure the consistency of a series of read and write operations within a transaction's scope. These transactions give you control over when to commit or roll back changes, isolating them from other client activity.

| Method       | Description                                                         |
| ------------ | ------------------------------------------------------------------- |
| `execute()`  | Similar to `execute()` except within the context of the transaction |
| `commit()`   | Commits all write statements in the transaction                     |
| `rollback()` | Rolls back the entire transaction                                   |
| `close()`    | Immediately stops the transaction                                   |

<CodeGroup>
  ```ts Rollback Usage
  try {
    const userId = "user123";
    const withdrawalAmount = 500;

    const transaction = await client.transaction("write");

    const balanceResult = await transaction.execute({
      sql: "SELECT balance FROM accounts WHERE userId = ?",
      args: [userId],
    });

    const currentBalance = balanceResult.rows[0]["balance"] as number;

    if (currentBalance >= withdrawalAmount) {
      await transaction.execute({
        sql: "UPDATE accounts SET balance = balance - ? WHERE userId = ?",
        args: [withdrawalAmount, userId],
      });
    } else {
      console.log("Insufficient funds");
      await transaction.rollback();
      return;
    }

    await transaction.commit();
  } catch (e) {
    console.error(e);
  }
  ```

  ```ts Batch Usage
  try {
    const records = [
      { name: "Alice", age: 30 },
      { name: "Bob", age: 25 },
      { name: "Charlie", age: 35 },
    ];

    const transaction = await client.transaction("write");

    for (const record of records) {
      await transaction.execute({
        sql: "INSERT INTO people (name, age) VALUES (?, ?)",
        args: [record.name, record.age],
      });
    }

    await transaction.commit();
  } catch (e) {
    console.error(e);
    await transaction.rollback();
  }
  ```

  ```ts Conditional Usage
  try {
    const productId = "prod456";
    const newPrice = 150;

    const transaction = await client.transaction("write");

    const productResult = await transaction.execute({
      sql: "SELECT price FROM products WHERE productId = ?",
      args: [productId],
    });

    const currentPrice = productResult.rows[0]["price"] as number;

    if (currentPrice > newPrice) {
      await transaction.execute({
        sql: "UPDATE products SET price = ? WHERE productId = ?",
        args: [newPrice, productId],
      });
    } else {
      console.log("New price is not lower than current price");
      await transaction.rollback();
      return;
    }

    await transaction.commit();
  } catch (e) {
    console.error(e);
  }
  ```
</CodeGroup>

<br />

<Warning>
  Interactive transactions in libSQL lock the database for writing until
  committed or rolled back, with a 5-second timeout. They can impact performance
  on high-latency or busy databases.
</Warning>

## ATTACH

You can attach multiple databases to the current connection using the `ATTACH` attachment:

```ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
});

const txn = await db.transaction("read");

await txn.execute('ATTACH "<database-id>" AS attached');

const rs = await txn.execute("SELECT * FROM attached.users");
```

<Info>
  Make sure to [allow `ATTACH`](/cli/db/config/attach/allow) and create a token
  with the permission to attach a database — [learn
  more](/features/attach-database)
</Info>


# Support

We're always here to help.

<CardGroup cols={2}>
  <Card title="Getting Started" href="/quickstart" icon="play">
    If you're new to Turso, the easiest way to get started is with this quickstart.
  </Card>

  <Card title="Discord" href="https://discord.gg/turso" icon="discord">
    Show off what you're working on, ask for help, and chat with the community.
  </Card>

  <Card title="Security" href="mailto:security@turso.tech" icon="envelope">
    If you spot something that doesn't look right, or you've discovered a security related bug or issue, let us know.
  </Card>

  <Card title="FAQs" href="https://turso.tech/pricing#faqs" icon="question">
    If you have a question about your account or billing, you'll find answers to most questions on our website.
  </Card>
</CardGroup>