apps/blog/content/blog/prisma-turso-ea-support-rxgd_tmy3uxx/index.mdx
Turso is an edge-hosted, distributed database that's based on libSQL, an open-source and open-contribution fork of SQLite, enabling you to bring data closer to your application and minimize query latency.
We’re excited to share that Prisma ORM is adding Early Access support for Turso. Let’s dive in!
SQLite is a self-contained, file-based open-source database known for its portability, reliability, and performance, even in environments with low memory. It’s also the perfect fit for small web applications because of its speed.
However, scaling SQLite introduces challenges:
Some of these challenges can be solved by tools such as LiteFS, which provides replication and database backups for SQLite.
On the other hand, Turso solved the above challenges by creating libSQL — a fork of SQLite that adds features that SQLite does not support yet. libSQL allows you to distribute and replicate SQLite, connect over HTTP, perform async operations, and embed SQLite as part of other programs as a primary database or replica of the primary database.
While Prisma has supported SQLite from its first release in 2019, libSQL differs from SQLite. For example, libSQL uses HTTP to connect to the database and uses a remote file over a local one, making Prisma and Turso incompatible until now.
Today, we’re excited to announce that Prisma support for Turso is now available in Early Access!
import { PrismaClient } from '@prisma/client'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
import { createClient } from '@libsql/client'
// Create a new instance of the libSQL database client
const libsql = createClient({
// @ts-expect-error
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN
})
// Create a Prisma "adapter" for libSQL
const adapter = new PrismaLibSQL(libsql)
// Pass the adapter option to the Prisma Client instance
const prisma = new PrismaClient({ adapter })
export default prisma
To start using Turso in your project, you must first enable the driverAdapters Preview feature flag. This will allow you to query your database using Turso’s driver adapter.
The
driverAdaptersfeature flag is part of the driver adapter initiative we're working on to enable you use other database drivers to connect to your database. Example driver adapters include PlanetScale, Neon, and libSQL. We’ll share more details soon! If you have not yet, fill out this survey, and leave us your email address for updates.
You will need to have the following tools installed:
You can set up a project using try-prisma if you don’t have an existing project using SQLite. Navigate to your working directory and copy the command below to set up the project:
npx try-prisma@latest --template typescript/script --path . --name turso-prisma --install npm
Navigate to the project and open it on your preferred code editor:
cd turso-prisma
First, create a database on Turso that your application will use. This step is necessary for creating the credentials required to configure Turso’s database client.
To create a database, run the following command on your terminal:
turso db create turso-prisma
Turso will also create a database in the region closest to your location.
Create an authentication token that will allow you to connect to the database:
turso db tokens create turso-prisma
Next, reveal the connection string details to connect to your database:
turso db show turso-prisma
Take note of the authentication token and connection string which will be used to connect to your database in the next step.
To get started using Turso:
Enable the driverAdapters Preview feature flag in your Prisma schema:
generator client {
provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
Create or update your .env file with the environment variables with the values from the “Create a database on Turso” step:
TURSO_AUTH_TOKEN="eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."
TURSO_DATABASE_URL="libsql://turso-prisma-random-user.turso.io"
Create the initial migration:
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > migration.sql
Apply the migration to your Turso database:
turso db shell turso-prisma < migration.sql
Install the latest version of Prisma Client:
npm install @prisma/client@latest
Install the libSQL database client and the driver adapter for Prisma Client:
npm install @prisma/adapter-libsql
npm install @libsql/client
Update your Prisma Client instance with the following snippet:
import { PrismaClient } from '@prisma/client'
// 1. Import libSQL and the Prisma libSQL driver adapter
import { PrismaLibSQL } from '@prisma/adapter-libsql'
import { createClient } from '@libsql/client'
// 2. Instantiate libSQL
const libsql = createClient({
// @ts-expect-error
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN
})
// 3. Instantiate the libSQL driver adapter
const adapter = new PrismaLibSQL(libsql)
// Pass the adapter option to the Prisma Client instance
const prisma = new PrismaClient({ adapter })
And that’s it!
You can now start querying your Turso database using Prisma Client.
If you cloned the typescript/script example, you can run npm run dev to insert and query data to confirm your changes were successful.
The setup above uses a single remote database. You can take it a step further by setting up database replicas. Turso automatically picks the closest replica to your app for read queries when you create replicas. No additional logic is required to define how the routing of the read queries should be handled. Write queries will be forwarded to the primary database.
Try it out and share your feedback! We encourage you to create an issue if you find something missing or run into a bug.
While Turso allows you to replicate SQLite globally, what if you could eliminate the extra network hop from your app to the remote replica? What if… you could move the database inside your application?
With Turso's newly announced embedded replicas, you can have a-copy of your primary, remote database inside your application, similar to how an embedded/local SQLite database works. You can try this out in your application using Prisma’s new support for Turso.
When your app initially establishes a connection to your database, the remote primary database will fulfill the query:
Then Turso will (1) create an embedded replica inside your application and (2)-copy data from your primary database to the replica so it is locally available:
The embedded replica will fulfill subsequent read queries. The libSQL client provides a sync() method which you can invoke to ensure the embedded replica's data remains fresh.
With embedded replicas, this setup guarantees your app is fast because the data will be readily available locally.
Like a read replica setup you may be familiar with, write operations are forwarded to the primary remote database and executed before being propagated to all embedded replicas.
To demonstrate the speed of embedded replicas, we created two example apps using the same primary database - and one variant uses an embedded replica.
For this sample test, the following query will be used:
await prisma.post.findMany({
where: { published: true },
select: {
id: true,
title: true,
author: true // relation
}
})
Below are screenshots of the timings for the same query on application startup:
Without an embedded replica:
Time: 154.390 ms
With an embedded replica:
Time: 7.883 ms
The query response significantly drops from 154.390 ms to 7.883 ms.
If you would like to try it out yourself, you can find the two example apps up on GitHub:
Embedded replicas are a relatively new feature of Turso, but some of the use cases you could use them for include:
It will be interesting to see what other use cases you will come up with for this new approach to database replicas.
We can't wait to see what you build with Turso and Prisma. We encourage you to try it out and let us know your thoughts.
We’re also working on supporting other serverless database drivers and edge function deployments. Take this short survey and leave us your email address for updates.
Be sure to share with us what you build on X/Twitter or Discord. 🙌