libSQL / SQLite
Tested with: libsql-server (sqld) 0.24 on Databasezy · zb CLI 0.1
libSQL is an open-source fork of SQLite that adds a network server. On Databasezy each instance runs libsql-server (sqld), so you get SQLite semantics with a URL and a password.
Overview
Section titled “Overview”Clients talk to the instance with the Hrana protocol over HTTPS or WebSockets. The certificate is publicly trusted, so there is no CA bundle to download. SQLite rules still apply: one writer at a time, unlimited readers.
| Status | Available |
|---|---|
| Category | Embedded SQL |
| Versions | 0.24 (newest is the default) |
| Protocol and port | HTTPS on 443 |
| Runtime | Single-node engine (ghcr.io/tursodatabase/libsql-server) |
| Backups | SQLite snapshot + WAL file per backup |
| Point-in-time recovery | No |
| Pause | Scale to zero |
| Free plan | Yes (size f0) |
| Licence | MIT |
Create an instance
Section titled “Create an instance”- Open the portal and choose New instance.
- Pick libSQL / SQLite and a version (0.24).
- Choose a size and region. On the Free plan the size is f0. Secure placement is listed only after your organization has signed the BAA.
- Check the hourly price and monthly estimate, then confirm. The Connect tab fills in when the instance is ready.
zb instances create --engine libsql --engine-version 0.24 \ --size s1 --region us-east --name libsql-demo --wait# On the Free plan, use --size f0
# Reveal the credentials once and store them in your secret managerzb instances credentials reveal libsql-democurl -sS https://api.databasezy.com/v1/orgs/$ZB_ORG/projects/$ZB_PROJECT/instances \ -H "Authorization: Bearer $ZB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "engine": "libsql", "engine_version": "0.24", "size": "s1", "region": "us-east", "name": "libsql-demo"}'
The response is 201 with the instance in status requested, or 202 when a
team approval policy applies. See the REST API reference.
Connect
Section titled “Connect”The instance uses HTTP basic authentication: the user app and a generated password, shown once like any credential
and rotated the same way. Send Authorization: Basic base64(app:password) with each Hrana request (for example
POST /v2/pipeline). Turso-style auth tokens (JWTs passed as authToken, sent as a Bearer header) are not accepted
by this server.
libSQL / SQLite listens on port 443 (HTTPS). Versions: 0.24. Replace the example host with the one on your instance's Connect tab; credentials are shown once at creation.
libsql://libsql-7f3k.us-east.databasezy.com?authToken=<token>import { createClient } from "@libsql/client";
export const db = createClient({ url: "libsql://libsql-7f3k.us-east.databasezy.com", // TLS with a publicly trusted certificate authToken: process.env.ZB_TOKEN,});
const rs = await db.execute("select sqlite_version() as v");console.log(rs.rows[0].v);Tested with: libSQL / SQLite 0.24 · @libsql/client 0.14
import asyncioimport osimport libsql_client
async def main(): async with libsql_client.create_client( url="libsql://libsql-7f3k.us-east.databasezy.com", auth_token=os.environ["ZB_TOKEN"] ) as client: rs = await client.execute("select sqlite_version() as v") print(rs.rows[0]["v"])
asyncio.run(main())Tested with: libSQL / SQLite 0.24 · libsql-client 0.3
package main
import ( "database/sql" "fmt" "os"
_ "github.com/tursodatabase/libsql-client-go/libsql")
func main() { url := fmt.Sprintf("libsql://libsql-7f3k.us-east.databasezy.com?authToken=%s", os.Getenv("ZB_TOKEN")) db, err := sql.Open("libsql", url) if err != nil { panic(err) } defer db.Close() var v string if err := db.QueryRow("select sqlite_version()").Scan(&v); err != nil { panic(err) } fmt.Println(v)}Tested with: libSQL / SQLite 0.24 · libsql-client-go v0.0.0-2024
use libsql::Builder;
#[tokio::main]async fn main() -> libsql::Result<()> { let token = std::env::var("ZB_TOKEN").expect("ZB_TOKEN"); let db = Builder::new_remote("libsql://libsql-7f3k.us-east.databasezy.com".to_string(), token).build().await?; let conn = db.connect()?; let mut rows = conn.query("select sqlite_version()", ()).await?; while let Some(row) = rows.next().await? { println!("{}", row.get::<String>(0)?); } Ok(())}Tested with: libSQL / SQLite 0.24 · libsql 0.6
// libSQL has no standard JDBC driver yet; call the Hrana HTTP pipeline directly.import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
public final class Db { public static void main(String[] args) throws Exception { var body = """ {"requests":[{"type":"execute","stmt":{"sql":"select sqlite_version()"}},{"type":"close"}]} """; var req = HttpRequest.newBuilder(URI.create("https://libsql-7f3k.us-east.databasezy.com/v2/pipeline")) .header("Authorization", "Bearer " + System.getenv("ZB_TOKEN")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)).build(); var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString()); System.out.println(res.body()); }}Tested with: libSQL / SQLite 0.24 · Java 21 java.net.http (Hrana v2 over HTTPS)
# Hrana v2 pipeline over HTTPS (works from any language with an HTTP client)curl -sS https://libsql-7f3k.us-east.databasezy.com/v2/pipeline \ -H "Authorization: Bearer $ZB_TOKEN" \ -H "Content-Type: application/json" \ -d '{"requests":[{"type":"execute","stmt":{"sql":"select sqlite_version()"}},{"type":"close"}]}'
# orzb connect libsql-7f3k --print # endpoint only: HTTP engines have no shellTested with: libSQL / SQLite 0.24 · curl 8 · sqld 0.24
Embedded replicas, which keep a local SQLite file in sync, need sqld’s replication endpoint, which Databasezy does not expose, so they are not available. The libSQL connection guide has more on clients.
See Connecting to Databasezy for host names, the CA bundle and the allow-list, which work the same for every engine.
Migrate in
Section titled “Migrate in”You can bring an existing libSQL / SQLite database in from these sources. Each links to a step-by-step guide.
| Source | How | Continuous sync | Guide status |
|---|---|---|---|
| Turso | Connection string, File upload | No | Available |
| Cloudflare D1 | File upload | No | Coming soon · phase 2 |
| Local files and dumps | File upload, Local tools (zb migrate --from local) | No | Available |
| Another Databasezy instance | Instance to instance | No | Coming soon · phase 2 |
Plain SQLite files (.sqlite, .db) upload as they are; WAL-mode files are checkpointed on upload. There is no
continuous sync, so take the dump during a short write freeze for busy databases.
How migrations work explains preflight, verification and cutover.
Backups and restore
Section titled “Backups and restore”Each backup is a consistent snapshot of the database file, taken with SQLite’s backup API, plus the write-ahead log file as it was at that moment, both uploaded to object storage. The log is not streamed continuously, so there is no point-in-time recovery: a restore returns the database as it was when a backup ran.
libSQL / SQLite backups use SQLite snapshot + WAL file per backup. They run inside the instance's namespace, stream straight to the cell's object storage and are checksummed on upload. How often they run and how long they are kept follows your plan's backup policy. A backup is always taken before a resize or a version upgrade.
Point-in-time recovery is not available for libSQL / SQLite. A restore returns the data as of a scheduled or manual backup. Restores create a new instance by default and leave the original untouched; an in-place restore asks you to type the instance name and takes a pre-change backup first.
zb backups create libsql-demo --label before-release # manual snapshotzb backups list libsql-demozb backups restore libsql-demo <backup-id> --name libsql-demo-restorePause and scale to zero
Section titled “Pause and scale to zero”libSQL / SQLite can scale to zero. A paused instance has no running pods and bills no compute; its storage and backups are kept and billed as usual. Connections are refused until you resume it. On the Free plan an instance pauses by itself after 15 minutes without connections and wakes on the next one; the gateway holds that connection for up to 30 seconds while it starts.
zb instances pause libsql-demozb instances resume libsql-demoSee Pause and resume for schedules, wake times and billing while paused.
Limits and sizes
Section titled “Limits and sizes”libSQL / SQLite runs on every size, including the Free plan's f0. The size sets the CPU, memory, storage ceiling and connection limit; the gateway refuses connections over the limit with a protocol error. Storage grows in steps up to the ceiling, and you can resize at any time.
| Size | vCPU | Memory | Max storage | Max connections | ≈ $ / month |
|---|---|---|---|---|---|
f0 | 0.063 | 512 MiB | 1 GB | 20 | Free |
s0 | 0.25 | 1 GiB | 20 GB | 60 | $10 |
s1 | 0.5 | 2 GiB | 50 GB | 100 | $15 |
s2 | 1 | 4 GiB | 200 GB | 200 | $60 |
m2 | 2 | 8 GiB | 500 GB | 400 | $110 |
m4 | 4 | 16 GiB | 1 TB | 800 | $210 |
l8 | 8 | 32 GiB | 4 TB | 1,500 | $410 |
l16 | 16 | 64 GiB | 8 TB | 3,000 | $960 |
xl32 | 32 | 128 GiB | 16 TB | 5,000 | $1,870 |
Full details, including hourly prices and burst CPU, are in the size catalogue; plan quotas are in limits and quotas.
Security
Section titled “Security”Treat the password like any secret: it travels in an HTTP header on every request. Do not ship it in a browser bundle or a mobile app; put a server or a serverless function in front.
- TLS on every connection. TLS 1.2 is the minimum and TLS 1.3 is preferred; plaintext is never
offered. Verify the server, not just the encryption: use
HTTPS with certificate verification. See TLS and the CA bundle. - IP allow-list. The gateway checks the client address before authentication, on every plan.
Manage it under Network → Allow-list in the portal or with
PUT /v1/orgs/{org}/instances/{id}/network. - Credentials. Generated inside the cell, shown once, never stored by the control plane. Rotate them with an overlap window so nothing breaks.
- Secure hosting. Secure placement (HIPAA-ready) is a per-instance option once your organization has signed the BAA: dedicated nodes, customer-managed keys and immutable backups. See Secure hosting and the BAA.
- Staff access. Databasezy staff cannot read your data without a grant you issue. See data confidentiality.
Can I open the database with the sqlite3 command-line tool?
Section titled “Can I open the database with the sqlite3 command-line tool?”Not over the network, and zb connect has no shell for HTTP engines. Run zb connect <id> --print for the endpoint and use a libSQL client library or the HTTP pipeline API.
Can I use embedded replicas?
Section titled “Can I use embedded replicas?”No. Embedded replicas (a client mode that keeps a local SQLite file in sync) need sqld’s replication endpoint, which Databasezy does not expose. Read through the HTTP API instead.
How many writers can I have?
Section titled “How many writers can I have?”One write transaction at a time, as with any SQLite database. Keep write transactions short; readers are not blocked.