VOOZH about

URL: https://dev.to/0012303/turso-has-a-free-api-heres-how-to-build-edge-first-apps-with-embedded-sqlite-2nd5

⇱ Turso Has a Free API — Here's How to Build Edge-First Apps with Embedded SQLite - DEV Community


Why Turso?

Turso brings SQLite to the edge. It's libSQL (a fork of SQLite) hosted globally with replication to 30+ locations. Your database is literally milliseconds from your users — everywhere.

Free tier: 9 GB storage, 500 databases, 25M row reads/month, 5 locations.

Getting Started

Install CLI

# macOS
brew install tursodatabase/tap/turso

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

turso auth login

Create Database

turso db create my-app
turso db show my-app --url
# libsql://my-app-yourname.turso.io

turso db tokens create my-app
# Your auth token

TypeScript (with Drizzle ORM)

import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
import { eq, desc, sql } from "drizzle-orm";

const client = createClient({
 url: "libsql://my-app-yourname.turso.io",
 authToken: "YOUR_TOKEN"
});

const db = drizzle(client);

// Define schema
const users = sqliteTable("users", {
 id: integer("id").primaryKey({ autoIncrement: true }),
 name: text("name").notNull(),
 email: text("email").unique().notNull(),
 plan: text("plan").default("free")
});

const posts = sqliteTable("posts", {
 id: integer("id").primaryKey({ autoIncrement: true }),
 title: text("title").notNull(),
 content: text("content"),
 authorId: integer("author_id").references(() => users.id),
 views: integer("views").default(0)
});

// Query
const topPosts = await db.select({
 title: posts.title,
 views: posts.views,
 author: users.name
}).from(posts)
 .innerJoin(users, eq(posts.authorId, users.id))
 .orderBy(desc(posts.views))
 .limit(10);

topPosts.forEach(p => console.log(`${p.title} by ${p.author} (${p.views} views)`));

Python

import libsql_experimental as libsql

conn = libsql.connect("my-app",
 sync_url="libsql://my-app-yourname.turso.io",
 auth_token="YOUR_TOKEN")
conn.sync()

# Create table
conn.execute("""
 CREATE TABLE IF NOT EXISTS products (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 name TEXT NOT NULL,
 price REAL NOT NULL,
 category TEXT,
 in_stock INTEGER DEFAULT 1
 )
""")

# Insert
conn.executemany(
 "INSERT INTO products (name, price, category) VALUES (?, ?, ?)",
 [("Widget", 9.99, "tools"), ("Gadget", 24.99, "electronics"), ("Doohickey", 14.99, "tools")]
)
conn.commit()
conn.sync() # Sync to cloud

# Query
results = conn.execute("""
 SELECT category, COUNT(*) as count, AVG(price) as avg_price
 FROM products WHERE in_stock = 1
 GROUP BY category ORDER BY avg_price DESC
""").fetchall()

for row in results:
 print(f"{row[0]}: {row[1]} products, avg ${row[2]:.2f}")

Embedded Replicas (Killer Feature)

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

// Local SQLite file synced with Turso cloud!
const client = createClient({
 url: "file:local-replica.db",
 syncUrl: "libsql://my-app-yourname.turso.io",
 authToken: "YOUR_TOKEN",
 syncInterval: 60 // sync every 60 seconds
});

// Reads are LOCAL (0ms latency!)
const result = await client.execute("SELECT * FROM products WHERE category = 'tools'");

// Writes go to cloud and sync back
await client.execute({ sql: "INSERT INTO products (name, price) VALUES (?, ?)", args: ["Thingamajig", 19.99] });

Turso vs Alternatives

Feature Turso Supabase PlanetScale D1
Engine SQLite PostgreSQL MySQL SQLite
Edge replicas Yes No No Yes
Embedded mode Yes No No No
Free storage 9 GB 500 MB 5 GB 5 GB
Locations 30+ 1 3+ 300+

Need data for your Turso-powered app? I build production-ready scrapers. Check out my Apify actors or email spinov001@gmail.com for custom data pipelines.

Using Turso? How are embedded replicas working for you? Share below!