Fix Turso Edge Database Integration with Next.js: Setup and Common Errors
Quick Answer
- Conclusion: Turso provides a SQLite-compatible edge database with HTTP/WebSocket protocol support, ideal for Next.js applications deployed on edge runtimes (Vercel Edge, Cloudflare Workers) or multi-tenant SaaS architectures requiring per-tenant database isolation.
- First checks: Verify
TURSO_DATABASE_URLandTURSO_AUTH_TOKENenvironment variables are set correctly. For Drizzle ORM integration, ensuredrizzle-ormis installed as a dependency (not devDependency) anddrizzle-kitis installed as a devDependency. - Minimal fix/config: Use
@libsql/clientfor direct Turso connections ordrizzle-orm/libsqlfor ORM-based access. The MCP server configuration requiresnpx -y @modelcontextprotocol/server-tursowith--urland--auth-tokenflags. - Version boundary: Turso's libSQL client works with Node.js 18+, edge runtimes (Vercel Edge, Cloudflare Workers), and any environment supporting Web APIs. The MCP server requires Node.js 18+.
What Problem It Solves
Turso solves the problem of running SQLite databases in distributed, edge-computing environments where traditional file-based SQLite access is impossible. It provides:
- Remote database access via HTTP/WebSocket protocol, eliminating the need for shared file systems
- Per-tenant database isolation without row-level security complexity
- Edge-native replication with local read replicas for zero-latency reads
- Automatic backups and cross-region replication for production reliability
For Next.js applications, Turso enables database queries directly from edge functions and server components without the latency of traditional cloud databases.
Installation and Quick Start
Install Turso CLI
BASHcurl -sSfL https://get.tur.so/install.sh | bash
Create a Turso Database
BASH# Login to Turso turso auth login # Create a new database turso db create my-nextjs-db # Get connection details turso db show my-nextjs-db --url turso db tokens create my-nextjs-db
Install Required Packages
For direct Turso client usage:
BASHnpm install @libsql/client
For Drizzle ORM integration:
BASHnpm install drizzle-orm @libsql/client npm install -D drizzle-kit
Note: drizzle-orm must be a regular dependency (not --save-dev) because it's used at runtime. drizzle-kit is a devDependency used only for migrations.
Minimal Working Configuration
Environment Variables
Create a .env.local file:
ENVTURSO_DATABASE_URL=libsql://my-nextjs-db.turso.io TURSO_AUTH_TOKEN=your-auth-token-here
Direct Client Connection
TYPESCRIPT// lib/db.ts import { createClient } from '@libsql/client'; const client = createClient({ url: process.env.TURSO_DATABASE_URL!, authToken: process.env.TURSO_AUTH_TOKEN!, }); export default client;
Drizzle ORM Configuration
TYPESCRIPT// drizzle.config.ts import type { Config } from 'drizzle-kit'; export default { schema: './lib/db/schema.ts', out: './drizzle', dialect: 'sqlite', dbCredentials: { url: process.env.TURSO_DATABASE_URL!, authToken: process.env.TURSO_AUTH_TOKEN!, }, } satisfies Config;
TYPESCRIPT// lib/db/schema.ts import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'; export const users = sqliteTable('users', { id: integer('id').primaryKey({ autoIncrement: true }), name: text('name').notNull(), email: text('email').notNull().unique(), });
MCP Server Configuration
For Claude Desktop or Cursor integration, add to claude_desktop_config.json or .cursor/mcp.json:
JSON{ "mcpServers": { "turso-mcp": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-turso", "--url", "${TURSO_DATABASE_URL}", "--auth-token", "${TURSO_AUTH_TOKEN}" ] } } }
Parameters and Environment Variables
| Parameter | Required | Description |
|---|---|---|
TURSO_DATABASE_URL | Yes | Turso database connection URL (e.g., libsql://my-db.turso.io) |
TURSO_AUTH_TOKEN | Yes | Authentication token for the Turso database |
TURSO_ORG | No | Turso organization name for platform API operations |
TURSO_PLATFORM_API_TOKEN | No | Platform API token for programmatic database management |
Common Errors and Fixes
Error: database is locked (SQLITE_BUSY)
Root cause: SQLite uses file-level locking. In high-concurrency write scenarios (>100 concurrent writes), the database may become temporarily locked.
Fix:
- Enable WAL mode:
PRAGMA journal_mode=WAL; - Implement retry logic with exponential backoff
- Reduce concurrent write operations
- Note: This error is rare in Turso's HTTP mode; if it occurs, check if you're using embedded replica mode
Error: Connection timeout (ETIMEDOUT)
Root cause: Network connectivity issues or incorrect database URL.
Fix:
- Verify the database URL:
turso db show <db-name> --url - Ensure HTTP/HTTPS protocols are allowed in your environment (especially in edge functions)
- Increase client timeout:
TYPESCRIPTconst client = createClient({ url: process.env.TURSO_DATABASE_URL!, authToken: process.env.TURSO_AUTH_TOKEN!, syncInterval: 60, // seconds });
Error: Authentication failed (401 Unauthorized)
Root cause: Invalid or expired authentication token.
Fix:
- Regenerate the token:
turso db tokens create <db-name> - Verify the token matches the correct database (each database has independent tokens)
- Check environment variable loading order and ensure
.env.localis properly loaded
Error: Paths not absolute (in drizzle-kit migrate)
Root cause: Drizzle Kit requires absolute or project-root-relative paths for schema files.
Fix:
- Use
path.resolveindrizzle.config.ts:
TYPESCRIPTimport path from 'path'; export default { schema: path.resolve(__dirname, './lib/db/schema.ts'), // ... };
- Run
npx drizzle-kit generatefrom the project root directory
Production Notes and Security Checks
Write Concurrency Limitations
SQLite's file-level locking limits write concurrency. For production applications with >100 concurrent writes, consider:
- Using WAL mode (
PRAGMA journal_mode=WAL) - Implementing write queues or batching
- Evaluating Postgres-based alternatives for write-heavy workloads
Token Security
- Rotate database access tokens regularly
- Never hardcode tokens in source code
- Use environment variables or secret management services
- Platform API tokens should be used only for management operations, not database access
Network Security
- Turso connections use TLS by default
- Verify client library versions support the latest TLS protocols
- In edge environments, ensure HTTPS is enforced
Backup Strategy
- Turso provides automatic backups
- Regularly export SQLite files to external storage as an additional safety measure
- Test backup restoration procedures periodically
Cross-Region Replication
- Turso replication is asynchronous
- Write operations return immediately after the primary region confirms
- Read replicas may have seconds of replication lag
- Design your application to tolerate eventual consistency for read replicas
FAQ
Q: What advantages does Turso offer over direct SQLite file access in MCP integration?
A: Turso provides HTTP/WebSocket protocol support, enabling remote database access without shared file systems. This is essential for MCP servers deployed in cloud or edge environments where direct file access is impossible. Turso also offers automatic backups, cross-region replication, and per-tenant database isolation—features not available in native SQLite.
Q: How does Turso's per-tenant database model work in MCP scenarios?
A: Each tenant gets an independent Turso database instance. The MCP server dynamically selects the correct database connection based on the tenant identifier: 1) Accept tenant ID as a parameter in MCP tool functions; 2) Query a metadata database for the tenant's connection details; 3) Create a temporary client using @libsql/client; 4) Execute queries and close the connection. Turso's HTTP protocol supports stateless connections, making this pattern efficient. Consider connection pooling or caching for performance optimization.
Q: How do I configure Turso MCP server in Claude Desktop or Cursor?
A: Add the following configuration to claude_desktop_config.json (Claude Desktop) or .cursor/mcp.json (Cursor):
JSON{ "mcpServers": { "turso": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-turso", "--url", "${TURSO_DATABASE_URL}", "--auth-token", "${TURSO_AUTH_TOKEN}"] } } }
Ensure TURSO_DATABASE_URL and TURSO_AUTH_TOKEN environment variables are set. For per-tenant databases, pass different URL and token values dynamically when starting the MCP server.