Skip to main content

Local development

A Turso database instance runs an open-source server called sqld. This server:

  • Handles incoming client connections over HTTP and websockets
  • Offers a JSON-based wire protocol for clients
  • Connects the client to the embedded libSQL database engine (a fork of SQLite) to execute queries
  • Manages the underlying database data in a SQLite database file

Turso adds additional features and configurations on top of sqld:

  • DNS and secure sockets with SSL
  • Client authentication with database tokens provided by the Turso CLI
  • World-wide instance location support
  • Serverless instance scaling
  • Automatic replication between instances

For daily development, you might be satisfied with the core features provided by sqld, without the additional features offered by Turso. You might also want to avoid any costs incurred by working with sqld instances managed by Turso. For these cases, you have three supported options for building and testing client code written with the [libSQL client SDKs]:

Use local SQLite database files

If you are building for an environment that offers read-write access to a local filesystem, using a SQLite database file is the easiest option. Some development environments for serverless backends don't offer access to a filesystem, such as Wrangler for Cloudflare Workers. Be sure to check the product documentation to find out if you have local filesystem access for your environment.

The libSQL client libraries support the use of local SQLite database files to service queries without any intermediate service. To configure a libSQL client to use a local file, you must provide a file: URL to the SDK when creating a client instance. This URL replaces the libsql URL you get from the Turso CLI for the purpose of local development.

For example, using the Python SDK:

import libsql_client

client = libsql_client.create_client_sync(

And using the JavaScript SDK:

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

const client = createClient({
url: "file:///path/to/file"

The JavaScript SDK only supports file URLs when using the default @libsql/client import (not the alternate web or http imports designed for some serverless backend environments). This works in Node.js-compatible environments that have access to the local filesystem.

You can also use relative file paths in the form file:relative/path/to/file.

Note that no authToken is required when connecting to a file URL. You may provide one, but it will have no effect on the client.

Run sqld using the Turso CLI

The Turso CLI comes with an embedded sqld that you can run with the following command:

$ turso dev

It provides a URL that you can use to connect the Turso CLI shell and client code. Learn more about turso dev in the embedded sqld documentation.

Build and run sqld separately

You can build and run an instance of sqld on your local machine. There are multiple ways to do this, and they are covered in the documentation to build and run sqld.

Using a local sqld instead of Turso

Once you have a local sqld running, you can use an http or ws URL in place of your libsql URL to connect to it. For example, sqld runs by default on port 8080, so the URL for that is ws:// This URL replaces the libsql URL you get from the Turso CLI for the purpose of local development.

sqld uses a dedicated directory to manage a SQLite database file along with other metadata. By default, the file lives in the relative path data.sqld/data where sqld was started.

About SQLite database files

SQLite has a documented file format for its database files. It's not necessary to understand this format, but you can use any tool that understands these files in order to work with them outside of your code. In particular, SQLite provides a command line shell for this purpose. This shell can make it easier for you to create and populate a database for your local development without having to use a client SDK.

SQLite does not have very flexible support for multiple processes. If you want to write to a database file manged by sqld or some other running process, you should first stop that process in order to avoid SQLITE_BUSY errors.