# 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.
Audit Logs are limited to paid plans.
```bash cURL
curl -L https://api.turso.tech/v1/organizations/{organizationName}/audit-logs \
-H 'Authorization: Bearer TOKEN'
```
# 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.
```bash cURL
curl -L -X GET 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/configuration' \
-H 'Authorization: Bearer TOKEN'
```
# Create Database
POST /v1/organizations/{organizationName}/databases
Creates a new database in a group for the organization or user.
```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",
});
```
# Generate Database Auth Token
POST /v1/organizations/{organizationName}/databases/{databaseName}/auth/tokens
Generates an authorization token for the specified database.
```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",
});
```
```json
{
"jwt": "TOKEN"
}
```
# Delete Database
DELETE /v1/organizations/{organizationName}/databases/{databaseName}
Delete a database belonging to the organization or user.
```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");
```
# Invalidate All Database Auth Tokens
POST /v1/organizations/{organizationName}/databases/{databaseName}/auth/rotate
Invalidates all authorization tokens for the specified database.
A short downtime is required to complete the changes.
```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");
```
# List Databases
GET /v1/organizations/{organizationName}/databases
Returns a list of databases belonging to the organization or user.
```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();
```
# 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.
```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");
```
# Retrieve Database
GET /v1/organizations/{organizationName}/databases/{databaseName}
Returns a database belonging to the organization or user.
```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");
```
# Retrieve Database Instance
GET /v1/organizations/{organizationName}/databases/{databaseName}/instances/{instanceName}
Return the individual database instance by name.
```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");
```
# 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.
```bash cURL
curl -L -X GET 'https://api.turso.tech/v1/organizations/{organizationName}/databases/{databaseName}/stats' \
-H 'Authorization: Bearer TOKEN'
```
# Update Database Configuration
PATCH /v1/organizations/{organizationName}/databases/{databaseName}/configuration
Update a database configuration belonging to the organization or user.
```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
}'
```
# 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.
```bash cURL
curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/databases/dumps' \
-H 'Authorization: Bearer TOKEN' \
-F 'file=@"~/Downloads/dump.sql"'
```
# Retrieve Database Usage
GET /v1/organizations/{organizationName}/databases/{databaseName}/usage
Fetch activity usage for a database in a given time period.
```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",
});
```
# Add Location to Group
POST /v1/organizations/{organizationName}/groups/{groupName}/locations/{location}
Adds a location to the specified group.
```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");
```
# Create Group
POST /v1/organizations/{organizationName}/groups
Creates a new group for the organization or user.
Creating more than one group is limited to Scaler, Pro and Enterprise plans.
```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'
});
```
# Create Group Auth Token
POST /v1/organizations/{organizationName}/groups/{groupName}/auth/tokens
Generates an authorization token for the specified group.
Tokens cannot be retrieved once created, and cannot be revoked individually.
```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",
});
```
```json
{
"jwt": "TOKEN"
}
```
# Delete Group
DELETE /v1/organizations/{organizationName}/groups/{groupName}
Delete a group belonging to the organization or user.
```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");
```
# Invalidate All Group Auth Tokens
POST /v1/organizations/{organizationName}/groups/{groupName}/auth/rotate
Invalidates all authorization tokens for the specified group.
```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");
```
# List Groups
GET /v1/organizations/{organizationName}/groups
Returns a list of groups belonging to the organization or user.
```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();
```
# Remove Location from Group
DELETE /v1/organizations/{organizationName}/groups/{groupName}/locations/{location}
Removes a location from the specified group.
```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");
```
# Retrieve Group
GET /v1/organizations/{organizationName}/groups/{groupName}
Returns a group belonging to the organization or user.
```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");
```
# Transfer Group
POST /v1/organizations/{organizationName}/groups/{groupName}/transfer
Transfer a group to another organization that you own or a member of.
You can only transfer groups to organizations you own or are an admin.
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.
```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"
}'
```
# Unarchive Group
POST /v1/organizations/{organizationName}/groups/{groupName}/unarchive
Unarchive a group that has been archived due to inactivity.
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.
```bash cURL
curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/unarchive' \
-H 'Authorization: Bearer TOKEN' \
```
# Update Databases in a Group
POST /v1/organizations/{organizationName}/groups/{groupName}/update
Updates all databases in the group to the latest libSQL version.
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.
```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");
```
# 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.
Get started with the Turso API to create your first database.
## API Resources
Start integrating the Turso API with your platform in a few simple steps.
# Closest Region
GET https://region.turso.io
Returns the closest region to the user's location.
#### Response
The location code for the server responding.
The location code for the client request.
```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();
```
```json 200
{
"server": "lhr",
"client": "lhr"
}
```
# List Locations
GET /v1/locations
Returns a list of locations where you can create or replicate databases.
```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();
```
# Create Invite
POST /v1/organizations/{organizationName}/invites
Invite a user (who isn't already a Turso user) to an organization.
If you want to invite someone who is already a registered Turso user, you can [add them](/api-reference/organizations/members/add) instead.
You must be an `owner` or `admin` to invite other users. **You can only invite users to a team and not your personal account.**
# Delete Invite
DELETE /v1/organizations/{organizationName}/invites/{email}
Delete an invite for the organization by email.
```bash cURL
curl -L -X DELETE https://api.turso.tech/v1/organizations/{organizationName}/invites/{email} \
-H 'Authorization: Bearer TOKEN'
```
# List Invites
GET /v1/organizations/{organizationName}/invites
Returns a list of invites for the organization.
```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");
```
# List Invoices
GET /v1/organizations/{organizationName}/invoices
Returns a list of invoices for the organization.
```bash cURL
curl -L https://api.turso.tech/v1/organizations/{organizationName}/invoices \
-H 'Authorization: Bearer TOKEN'
```
# List Organizations
GET /v1/organizations
Returns a list of organizations the authenticated user owns or is a member of.
```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();
```
# Add Member
POST /v1/organizations/{organizationName}/members
Add an existing Turso user to an organization.
If you want to add someone who is not a registered Turso user, you can [create an invite](/api-reference/organizations/invites/create) instead.
You must be an `owner` or `admin` to add other members. **You can only add users to a team and not your personal account.**
# List Members
GET /v1/organizations/{organizationName}/members
Returns a list of members part of the organization.
```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");
```
# Remove Member
DELETE /v1/organizations/{organizationName}/members/{username}
Remove a user from the organization by username.
```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");
```
# List Plans
GET /v1/organizations/{organizationName}/plans
Returns a list of available plans and their quotas.
```bash cURL
curl -L https://api.turso.tech/v1/organizations/{organizationName}/plans \
-H 'Authorization: Bearer TOKEN'
```
# Current Subscription
GET /v1/organizations/{organizationName}/subscription
Returns the current subscription details for the organization.
```bash cURL
curl -L https://api.turso.tech/v1/organizations/{organizationName}/subscription \
-H 'Authorization: Bearer TOKEN'
```
# Update Organization
PATCH /v1/organizations/{organizationName}
Update an organization you own or are a member of.
```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,
});
```
# Organization Usage
GET /v1/organizations/{organizationName}/usage
Fetch current billing cycle usage for an organization.
```bash cURL
curl -L https://api.turso.tech/v1/organizations/{organizationName}/usage \
-H 'Authorization: Bearer TOKEN'
```
# Quickstart
Get started with Turso API in a few easy steps.
Make sure to [install the Turso CLI](/cli/installation) if you haven't
already.
```bash Signup
turso auth signup
```
```bash Login
turso auth login
```
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
```
Now create a new API Token using the Turso CLI:
```bash
turso auth api-tokens mint quickstart
```
Make sure to save the token somewhere safe. We'll need it next.
Before we can create a group or database in a specific region, we'll need to fetch the list of available regions:
```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();
```
The `organizationName` is the name of your organization or personal account.
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`:
```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");
```
Now create your first database in the group you created above:
```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");
```
Add another location to your group to replicate your database to another region:
```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");
```
You now have a database, distributed across multiple regions that you can connect to using one of the official or experimental SDKs:
# 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.
The `token` in the response is never revealed again. Store this somewhere safe, and never share or commit it to source control.
```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");
```
# List API Tokens
GET /v1/auth/api-tokens
Returns a list of API tokens belonging to a user.
```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();
```
# Revoke API Token
DELETE /v1/auth/api-tokens/{tokenName}
Revokes the provided API token belonging to a user.
```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");
```
# Validate API Token
GET /v1/auth/validate
Validates an API token belonging to a user.
```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("...");
```
# 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
```
# auth api-tokens revoke
To revoke an API token for the current organization, run the following command:
```bash
turso auth api-tokens revoke
```
# auth login
To authenticate the Turso CLI with your account, run the following command:
```bash
turso auth login
```
If you're using Windows with WSL or a remote CI/CD environment, pass the --headless flag.
## 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
```
If you're using Windows with WSL or a remote CI/CD environment, pass the --headless flag.
## 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.
If you're using Windows with WSL or a remote CI/CD environment, pass the `--headless` flag.
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
```
The Turso CLI requires you to reauthenticate after one week. Don't share your token.
## `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
```
You will be redirected to a webpage where you can select a date and time for the meeting.
# 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
```
# db config attach disallow
Disallow a database to be attached by other databases:
```bash
turso db config attach disallow
```
# db config attach show
Show the attach configuration for a database:
```bash
turso db config attach show
```
# db create
You can create a new database in a specific group using the following command:
```bash
turso db create [database-name]
```
The `[database-name]` argument is optional. If you don't provide a name, the Turso team will use the name of your project.
If you have more than one group, you will need to pass the `--group` flag.
## 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.
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 ` | The type of database to create. Defaults to to `regular`. |
| `--schema ` | 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
```
### 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
```
The file size is limited to 2GB.
### 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
```
### 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 --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
```
### 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
```
Using `--enable-extensions` will enable extensions on all databases in the group.
### 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
```
The parent database must be created using the `--type schema` flag.
# db destroy
You can destroy a database, including any replicas by using the following command:
```bash
turso db destroy [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
```
## 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:
```bash Command
turso db inspect --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';
```
# 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 ` | Filter databases by parent schema. |
| `--group ` | 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 [sql] [flags]
```
## Flags
| Flag | Description |
| ---------------------------- | ------------------------------------------------------------------ |
| `--attach ` | List of database names with attach claim to be added to the token. |
| `--instance ` | Connect to the specified database instance. |
| `--location ` | Connect to the database at the specified location. |
| `--proxy ` | 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 "SELECT * FROM users"
```
### Database dump
You can dump the contents of a Turso database using the following command:
```bash
turso db shell .dump > dump.sql
```
The `.dump` can be used to rebuild a database and doesn't contain any libSQL or SQLite internal tables.
### Load from dump
You can load a dump file into a new database using the following command:
```bash
turso db shell < 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 --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 [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 [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 --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 --expiration 7d3h2m1s
```
# db tokens invalidate
You can invalidate all tokens for a database by running the following command:
```bash
turso db tokens invalidate [flags]
```
## Flags
| Flag | Description |
| ------------- | ---------------------------------------------------- |
| `-y`, `--yes` | Confirms the invalidation of all existing db tokens. |
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.
# 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 [flags]
```
Creating more than one group is limited to Scaler, Pro and Enterprise plans.
Turso will automatically detect the closest region and use that as the primary region. You can override this by specifying the `--location` flag.
## 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 [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 [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 locations remove
You can remove locations from a group using the command below:
```bash
turso group locations remove <...location-codes>
```
All database replicas belonging to the provided group will be immediately removed from the locations.
# 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 [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 --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 --expiration 7d
```
# group tokens invalidate
You can invalidate all tokens for a group by running the command:
```bash
turso group tokens invalidate [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 [flags]
```
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.
## 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
```
Databases get archived after 10 days of inactivity for users on a free plan — [learn more](/features/scale-to-zero).
# group update
You can update the group, including all databases the following command:
```bash
turso group update [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 --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
```
If you're using Windows with WSL or a remote CI/CD environment, pass the `--headless` flag.
# 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).
Begin by installing the Turso CLI:
```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
```
Now signup or login:
```bash Signup
turso auth signup
```
```bash Login
turso auth login
```
```bash Signup (WSL)
turso auth signup --headless
```
```bash Login (WSL)
turso auth login --headless
```
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. |
# 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
```
You will be asked to add a payment method and subscribe to the Scaler plan to successfully create a new organization.
# destroy
To delete an existing organization that you own, run the following command:
```bash
turso org destroy
```
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.
# 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 [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 [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
```
This command is only available to active organizations, use [`org switch`](/cli/org/switch) if you're currently authenticated with your personal account.
# org members rm
To remove a member from the current organization, use the following command:
```bash
turso org members rm
```
# org switch
To switch the current active organization for the CLI, use the following command:
```bash
turso org switch
```
# plan overages disable
You can disable overages for the current repository by running the following command:
```bash
turso plan overages disable
```
Any overages that have already been incurred will still be charged.
# 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
```
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.
# 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
```
You will need to add your credit card details to your account before you can upgrade to a paid plan.
# 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.
Learn more about [data and connections](/data-and-connections).
### 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.
Enterprise plans can have higher limits on storage.
![Turso Database Groups and Replication](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/concepts/database-group.png)
Creating more than one group is limited to Scaler, Pro and Enterprise plans.
You can add additional groups if you have overages enabled.
## 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.
| 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 |
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).
# 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.
Full support for vector search in the Turso platform starts from version `v0.24.24`
(use the `turso group show ` command to check the group version).
## 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.
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.
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.
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 |
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.
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.
### 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
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.
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.
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;
```
### 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.
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
```
### 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.
The DiskANN algorithm trades search accuracy for speed, so LibSQL queries may
return slightly suboptimal neighbors for tables with a large number of rows.
### 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));
```
Vector index works only for column with one of the vector types described
above
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. 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. Default: $3 \sqrt{D}$ where $D$ -- dimensionality of vector column |
| `compress_neighbors` | `float1bit`\|`float8`\| `float16`\|`floatb16`\| `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. 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. 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. 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. Default: `70` |
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.
### Index usage
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.
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.
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.
The `libsql_vector_idx` marker function is **required** and used by libSQL to
distinguish `ANN`-indices from ordinary B-Tree indices.
```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.
### 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).
You will first need to enable the `ATTACH` feature on the database(s) you want to attach:
```bash
turso db config attach allow
```
You now need to retrieve the **Database ID** for the database you want to `ATTACH`:
```bash
turso db show
```
Now pass the names of the databases via the `--attach` flag when connecting to your database(s):
```bash
turso db shell --attach <...database-name(s)>
```
Now once connected to the database you can invoke an `ATTACH` statement to connect the other database(s):
```sql
ATTACH "" AS my_db;
```
Execute a query using the alias for any attached database(s):
```sql
SELECT * FROM my_db.my_table;
```
### 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).
You will first need to enable the `ATTACH` feature on the database(s) you want to attach:
```bash
turso db config attach allow
```
You now need to retrieve the **Database ID** for the database you want to `ATTACH`:
```bash
turso db show
```
Now create a token for the libSQL client with the `attach` permission for the database you want to attach:
```bash
turso db tokens create --attach
```
Use a [Client SDK](/sdk) to attach the desired database within a read transaction:
```ts @libsql/client
import { createClient } from "@libsql/client";
const client = createClient({
syncUrl: "libsql://...",
authToken: "...",
});
const txn = await db.transaction("read");
await txn.execute('ATTACH "" AS my_db');
const rs = await txn.execute("SELECT * FROM my_db.my_table");
```
## 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:
```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"
}
}'
```
Refer to the following references for more details about all arguments:
## 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.
## 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
Turso automatically handles keeping replicas updated — [learn more](/data-and-connections).
## 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):
```bash CLI
turso group locations add
```
```bash Platform API
curl -L -X POST 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
-H 'Authorization: Bearer TOKEN'
```
## 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):
```bash CLI
turso group locations remove <...location-codes>
```
```bash Platform API
curl -L -X DELETE 'https://api.turso.tech/v1/organizations/{organizationName}/groups/{groupName}/locations/{location}' \
-H 'Authorization: Bearer TOKEN'
```
# 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:
The encryption key used should be generated and managed by you.
## 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:
```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()?;
```
You can sync changes from the remote database to the local replica manually:
```ts TypeScript
await client.sync();
```
```go Go
if err := connector.Sync(); err != nil {
fmt.Println("Error syncing database:", err)
}
```
```rust Rust
client.sync().await?;
```
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.
## 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
Deploy a JavaScript project with Embedded Replicas to Fly.io
Deploy a JavaScript/Rust project with Embedded Replicas to Koyeb
Deploy a JavaScript/Rust project with Embedded Replicas to Railway
Deploy a JavaScript project with Embedded Replicas to Render
Deploy a JavaScript/Rust project with Embedded Replicas to Akamai
# 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)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
You will want to store these as environment variables.
Fork one of the following embedded replica projects from GitHub
See the full source code
See the full source code
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.
SSH into your server, clone the project from GitHub, and follow its README instructions to set it up.
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.
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.
# 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/)
You should have an application ready using your Turso database that you want to deploy to Fly.
Using the Fly CLI, launch it:
```bash
fly launch
```
Your application will automatically deploy to Fly, but we're not ready yet.
Now create a volume that will be used to store the embedded replica(s):
```bash
fly volumes create libsql_data
```
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/
```
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:./local.db",
syncUrl: process.env.TURSO_DATABASE_URL,
syncToken: process.env.TURSO_AUTH_TOKEN,
syncInterval: 60000,
});
```
```bash
fly deploy
```
# 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/)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
You will want to store these as environment variables.
Fork one of the following embedded replica project from GitHub
See the full source code
See the full source code
Or, you can:
1. Create a new app in the Koyeb control panel.
2. Select GitHub as the deployment option.
3. Import the GitHub project to Koyeb.
![Koyeb deploy page - environment variables](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/platforms/koyeb-env-variables.png)
Click the **Deploy** button at the bottom to deploy your web service.
# 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)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
You will want to store these as environment variables.
Fork and clone the following embedded replica project from GitHub locally:
See the full source code
See the full source code
Run the following command to create a new Railway project. Provide the project's name when prompted.
```sh
railway init
```
[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.
Run the following command to list and select the service to link to your application:
```sh
railway service
```
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
```
Run the following command to deploy your application:
```sh
railway up
```
Make sure you [expose your application to the internet](https://docs.railway.app/guides/public-networking) to make it accessible from the public network.
If you are on a free plan, you'll need to connect your Railway account to GitHub to have access to code deployments.
# 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/)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
You will want to store these as environment variables.
Fork the following embedded replica project from GitHub locally:
See the full source code
Or, you can:
Create a new Render **Web Service** by clicking on the "New Web Service" button on the Web Services card inside you Render dashboard.
1. Select "build and deploy from a Git repository" and proceed to the next page.
2. Click on "Connect" for your target project repository
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)
Scroll to the bottom of the web service configuration page and click on "Create Web Service".
# 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.
This feature is currently in beta. [Join us in Discord](https://discord.gg/turso) to provide feedback and report any issues.
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.
## 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).
### Turso CLI
Make sure you have the [Turso CLI](/cli/installation) installed, and [logged in](/cli/auth/login).
Create a single database using the `--type` flag set to `schema`:
```bash
turso db create parent-db --type 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
```
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
```
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);"
```
### Platform API
Make sure you have an API Token, and know your Organization name:
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
}'
```
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
```
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"
}'
```
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);"
```
## 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
# 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.
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.
## 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.
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.
## Usage
```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"
}
}'
```
Refer to the following references for more details about all arguments:
## 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.
[Database groups](/concepts#groups) with extended inactivity (**10 days**) will require a manual "unarchive" operation using the [CLI](/cli/group/unarchive) or API.
# 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)
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.
## 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.
Improve query efficiency by storing aggregate values in a separate table and
updating it transactionally with the base table changes.
### Full Table Scans
Queries lacking index support perform a full table scan, incurring a row scan for each table row.
Seek strategies to minimize costly table scans.
### 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.
`ALTER TABLE` actions may also lead to row reads, adding another layer to consider when modifying table structures.
## 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.
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.
## 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.
![Turso Quickstart](https://mintlify.s3-us-west-1.amazonaws.com/turso/images/turso-banner.png)
## New to Turso?
Turso is a SQLite-compatible database built on [libSQL](/libsql), the Open Contribution fork of SQLite.
}
href="/quickstart"
>
Create your first database
}
href="/features/embedded-replicas/introduction"
>
Get zero latency reads on-device
}
href="/features/ai-and-embeddings"
>
Vector is just another datatype
Share schema across multiple databases
Get low latency with edge replicas
}
title="Backups and Recovery"
href="/features/point-in-time-recovery"
>
Restore your database to any point in time
## Start building
Learn how to manage, distribute and integrate your databases with the CLI, API and SDKs.
Manage groups, databases, and API tokens with the Turso CLI.
Manage groups, databases, and API tokens with the Turso API.
}
href="/sdk"
>
Connect and integrate Turso into your application with one of our libSQL
drivers.
Learn how to work with Turso and your favorite language or framework.
## Join the community
Join the Turso community to ask questions, discuss best practices, and share tips.
# 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.
Browse the libSQL source code on GitHub, report issues, feature requests and contribute using pull requests.
Join the community on Discord to talk about the development of libSQL.
## 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.
The encryption key used should be generated and managed by you.
## Extensions
Extensions are experimental. [Join us on Discord](https://discord.gg/turso) to add your suggestions and feedback.
If you're looking to enable vector extensions, you should instead consider
using the native [libSQL vector datatype](/features/ai-and-embeddings).
| 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):
```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"
}'
```
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 --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:
```bash
turso db shell your-database .dump > dump.sql
```
```bash
cat dump.sql | sqlite3 local.db
```
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.
## 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:
```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"
)
```
You don't need to provide an `authToken` in development.
It's recommended to use environment variables for both `url` and `authToken` for a seamless developer experience.
## 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:
```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"
)
```
Changes will be lost when you stop the server.
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:
## 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.
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.
## 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
We'll be using the Turso CLI throughout this quickstart to manage databases, create replicas in other regions, and connect to the database shell.
```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
```
The next command will open your browser to sign up:
```bash Signup
turso auth signup
```
```bash Login
turso auth login
```
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
```
Congratulations, you created a database! Now connect to it with the `shell` command:
```bash
turso db shell my-db
```
Replace `my-db` with the name of your database if you named it differently.
Now create a table for `users` using SQL:
```sql
CREATE TABLE users (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
```
Then insert a row into the `users` table:
```sql
INSERT INTO users (name) VALUES ("Iku");
```
Finally, query for all `users`:
```sql
SELECT * FROM users;
```
When you're ready to move onto the next step, you'll want to to quit the shell:
```sql
.quit
```
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.
You're now ready to connect your application to your database. Pick from one of the SDKs below to continue:
# 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:
```bash libSQL
libsql://[DB-NAME]-[ORG-NAME].turso.io
```
```bash HTTPS
https://[DB-NAME]-[ORG-NAME].turso.io
```
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.
## 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.
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)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
To use libSQL with C, you need to build the library from source:
Build from source code
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
```
You must first initialize libSQL, create a `libsql_database_t` object, and then open a `libsql_connection_t` to it:
```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);
```
```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);
```
```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);
```
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:
```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);
```
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);
}
```
# C Reference
libSQL C Reference
## 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.
Build from source code
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:
```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));
```
## 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)
```bash
flutter pub add drift_libsql drift drift_flutter dev:build_runner dev:drift_dev
```
```dart
class TaskTable extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text()();
TextColumn get description => text()();
BoolColumn get completed => boolean()();
}
```
```dart
@DriftDatabase(tables: [TaskTable])
class AppDatabase extends _$AppDatabase {
AppDatabase(super.e);
@override
int get schemaVersion => 1;
}
```
```bash
dart run build_runner build
```
```dart
final db = AppDatabase(DriftLibsqlDatabase(
"${dir.path}/replica.db",
syncUrl: url,
authToken: token,
readYourWrites: true,
syncIntervalSeconds: 3,
));
```
```dart
await db.into(db.taskTable).insert(TaskTableCompanion.insert(
title: task.title,
description: task.description,
completed: task.completed));
```
# Turso Quickstart (Flutter / Dart)
Get started with Flutter and Dart using the libSQL client in a few simple steps
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.
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)
You will need an existing database to continue. If you don't have one, [create one](/quickstart).
You will want to store these as environment variables.
```bash
flutter pub add libsql_dart
```
Now connect to your local or remote database using the `LibsqlClient` constructor:
```dart
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';
final client = LibsqlClient(path)
..authToken = ''
..syncUrl = ''
..syncIntervalSeconds = 5
..readYourWrites = true;
```
```dart File
final dir = await getApplicationCacheDirectory();
final path = '${dir.path}/local.db';
final client = LibsqlClient(path);
```
```dart In-Memory
final client = LibsqlClient(":memory:");
```
```dart
final client = LibsqlClient('')
..authToken = '';
```
```dart
await client.connect();
```
```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();
```
If you need to use placeholders for values, you can do that:
```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})
```
When using embedded replicas you should call `sync()` on the connector to sync your local database with the primary database.
```dart
await client.sync();
```
# 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('')
..authToken = '';
```
## 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 = ''
..syncUrl = ''
..readYourWrites = true;
```
### 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 = ''
..syncUrl = ''
..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 = '';
```
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