Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Turso Driver Laravel Laravel Package

tursodatabase/turso-driver-laravel

Laravel database driver for Turso (libSQL) that lets your app use Turso's SQLite-compatible embedded and remote databases through Laravel's native DB layer. Add a connection and keep using Eloquent, migrations, and the query builder with edge-friendly, replicated SQLite storage.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package and its native dependency.

    composer require tursodatabase/turso-driver-laravel
    

    This package is a Laravel database driver that talks to libSQL/Turso using native bindings. Confirm your PHP runtime has the required libSQL extension/binding available (check the README's requirements section — this is the step most likely to fail silently, with a "could not find driver" or class-not-found error).

  2. Add the connection to config/database.php.

    'turso' => [
        'driver'     => 'turso',
        'url'        => env('TURSO_DATABASE_URL'),      // libsql://... or file:...
        'auth_token' => env('TURSO_AUTH_TOKEN'),        // omit for local files
    ],
    

    Put TURSO_DATABASE_URL and TURSO_AUTH_TOKEN in .env. Use a file: URL (e.g. file:database/local.sqlite) for local development and an libsql:// / https:// URL plus token for remote Turso databases.

  3. Point Laravel at it.

    DB_CONNECTION=turso
    

    The service provider is auto-discovered; no manual registration should be needed. Verify with php artisan tinker → DB::connection()->getPdo().

  4. Run your schema.

    php artisan migrate --seed
    

    The driver speaks the SQLite dialect, so standard Laravel migrations work — but only those that map cleanly to SQLite (see Gotchas).

  5. First real use case: a new Laravel app that wants SQLite's simplicity with a managed, replicable backend, or an existing SQLite app migrating to Turso for edge/read-replica access. Start by running your existing migrations against a file: database locally, then flip TURSO_DATABASE_URL to the remote URL to validate the network path.

Where to look first: the package README's connection config example and its requirements/extension section, then your config/database.php. If anything fails, check php -m for the native extension before debugging Laravel config.

Implementation Patterns

Use the database layer exactly as you would with SQLite. Eloquent, the query builder, factories, seeders, and DB::transaction() all work unchanged. The driver only changes the transport and grammar resolution; application code shouldn't branch on turso.

Connection-per-environment is the main config pattern.

'turso' => [
    'driver'     => 'turso',
    'url'        => env('TURSO_DATABASE_URL', 'file:database/local.sqlite'),
    'auth_token' => env('TURSO_AUTH_TOKEN'),
],

Keep a single turso connection and swap the URL/token per environment. Avoid hardcoding remote URLs in code; treat the token as a secret and never commit it.

Batch your writes. Because remote Turso goes over the network, N+1 inserts are far more expensive than with a local MySQL/SQLite socket. Use DB::table(...)->insert($rows) with arrays, upsert(), and chunked Model::insert() instead of per-row save() loops. Wrap multi-statement writes in a single transaction to collapse round trips:

DB::transaction(function () use ($rows) {
    Order::insert($rows);           // one round trip
    DB::table('outbox')->insert($events);
});

Read replicas / embedded replicas. For read-heavy workloads, the value of Turso is replication. If the driver exposes an embedded-replica URL option, point reads at the replica and writes at the primary (either via a second connection entry or by URL selection at boot). Keep the read path tolerant of slightly stale data.

Use it for the standard Laravel database-backed subsystems, cautiously. database cache, sessions, and queue drivers will function, but they generate constant small writes. On a remote Turso database this becomes latency-sensitive; for queues, prefer a dedicated driver or batch job processing. It's a great fit for low-traffic apps and prototypes, less so for high-throughput job queues.

Testing pattern: run the test suite against a file: database (or :memory: if supported by the driver) rather than the remote URL. Use RefreshDatabase with a local file and a dedicated phpunit.xml env override:

<env name="DB_CONNECTION" value="turso"/>
<env name="TURSO_DATABASE_URL" value="file:database/testing.sqlite"/>

Never point CI at a shared remote database with RefreshDatabase — it will migrate down your real data.

Migrations as ordinary Laravel migrations. Use Schema::create, $table->id(), string, text, json, timestamp, etc. Prefer simple column types; verify anything exotic against SQLite's type affinity before relying on it.

Gotchas and Tips

  • Native extension is the #1 failure point. "could not find driver" or a missing class almost always means the libSQL binding/extension isn't installed for the PHP binary you're running (CLI vs FPM differ). Check php -m and the package's requirements before touching Laravel config.

  • You inherit every SQLite limitation. No native ENUM, no FULLTEXT unless compiled in, limited ALTER TABLE (SQLite supports add-column and a narrow set of alters; modifying/dropping columns relies on Laravel's table-rebuild strategy and can fail on complex tables). Plan schema changes early; don't assume MySQL-style migrations will port.

  • Foreign keys may be off by default. SQLite requires PRAGMA foreign_keys = ON per connection. If you rely on FK cascades, verify the driver enables it; otherwise add it to your connection bootstrap (DB::statement('PRAGMA foreign_keys = ON') in a service provider or after-connect hook if the driver supports one).

  • Type affinity, not strict typing. SQLite will happily store a string in an integer column. Validate and cast in your models; don't depend on the DB to reject bad types. Use $casts on Eloquent models aggressively.

  • Concurrency model is single-writer. libSQL/SQLite serializes writes. High-concurrency write workloads (job queues, counters, high-traffic web writes) will contend and surface as lock/busy errors or latency. Use transactions for multi-statement writes, keep them short, and add retry logic around SQLSTATE busy errors.

  • Network latency changes your query patterns. Queries that were cheap locally become measurable round trips. Watch DB::listen() in a service provider or enable query logging to spot N+1s; the database queue and cache drivers are the usual offenders.

  • Migration safety on remote databases. migrate:fresh and RefreshDatabase are destructive. Gate them behind environment checks and never let CI hit a shared remote URL.

  • Token and URL handling. The auth token is a bearer secret — keep it in .env/secrets manager, not in config committed to git. Some Turso URLs require the libsql:// scheme while others accept https://; match the scheme the driver expects or you'll get opaque connection errors.

  • Debugging tips. Use DB::listen() and Log::debug for query timings; php artisan tinker to test the connection in isolation; test against a file: database to separate "driver broken" from "network/token broken." If a specific query fails, run it through sqlite3 locally — the SQL dialect mismatch will usually reveal itself immediately.

  • Extension points. If you need to tweak grammar or connection behavior, the driver typically registers a connection resolver and grammar via the service provider. You can subclass them and rebind in AppServiceProvider::register() — useful for custom PRAGMAs or retry behavior.

  • Maturity caution. This is a community SDK with modest adoption (~98 stars). Pin the version in composer.json, review release notes on upgrade, and have a fallback plan (standard SQLite file driver locally, or plain libSQL client for remote) if the driver lags Laravel releases. Test major Laravel upgrades against it before deploying.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console