A SvelteKit application does not need Turso Cloud to use Turso. The @tursodatabase/database package can open a database file directly inside the Node.js process:
import { connect } from '@tursodatabase/database';
const db = await connect('local.db');There is no database URL, authentication token, or network round trip in this configuration. The application reads and writes a local database file.
That distinction matters because Turso has separate packages for different execution models. A cloud connection and an embedded database solve different deployment problems even though both expose familiar SQL APIs.
Keep the database behind SvelteKit’s server boundary
An embedded database belongs in server-only code. A useful layout is:
src/
├── lib/
│ └── server/
│ └── db.ts
└── routes/
└── users/
├── +page.svelte
└── +page.server.tsPlacing the connection module under $lib/server prevents it from being imported into browser code through normal SvelteKit module boundaries.
// src/lib/server/db.ts
import { connect } from '@tursodatabase/database';
export const db = await connect('local.db');A server load function can query it directly:
// src/routes/users/+page.server.ts
import { db } from '$lib/server/db';
export async function load() {
const stmt = db.prepare(
'SELECT id, name FROM users ORDER BY id DESC'
);
return { users: stmt.all() };
}The browser receives the serialized result from SvelteKit. It never opens the database file itself.
Local means local to the server process
The filename passed to connect identifies storage on the machine running SvelteKit. On a laptop, the database is on that laptop. In a container, it is inside that container unless its directory is backed by a mounted volume. On a VPS, it is on that VPS.
The architecture is therefore:
browser
|
v
SvelteKit server
|
| local file access
v
local.dbThere is no database network hop. The tradeoff is that filesystem lifetime becomes part of the application’s data architecture.
Put writes in server actions
A form action can write to the embedded database without exposing database access to the client:
// src/routes/users/+page.server.ts
import { fail } from '@sveltejs/kit';
import { db } from '$lib/server/db';
export const actions = {
create: async ({ request }) => {
const form = await request.formData();
const name = String(form.get('name') ?? '').trim();
if (!name) {
return fail(400, { name, missing: true });
}
const stmt = db.prepare(
'INSERT INTO users (name) VALUES (?)'
);
stmt.run([name]);
return { success: true };
}
};Parameter binding is significant here. User input should be passed as values instead of being concatenated into SQL strings.
Schema initialization follows the same server-only boundary. A small application can create tables explicitly at startup, while a larger application should normally keep ordered migrations so schema changes remain reproducible.
Embedded Turso is not Turso Cloud
For local storage, the dependency is:
npm install @tursodatabase/databaseand the connection is file-oriented:
import { connect } from '@tursodatabase/database';
const db = await connect('local.db');Current Turso material uses @tursodatabase/serverless for direct remote cloud access. That connection receives a remote URL and authentication token.
The two models have different boundaries:
@tursodatabase/database
-> embedded database
-> local file
-> no Turso Cloud account required
@tursodatabase/serverless
-> remote database
-> network connection
-> Turso Cloud URL + authenticationAn embedded database does not consume a Turso Cloud database quota merely because the database engine comes from Turso. Turso describes embedded use as free; its hosted cloud service has separate plans and limits.
Deployment is the critical constraint
Local development can hide the most important property of embedded storage: the database survives only if its filesystem survives.
A long-running Node.js process on a VPS is a straightforward fit:
VPS
├── SvelteKit Node process
└── /var/lib/myapp/local.dbA container can also work when the database directory uses persistent storage:
container
|
+-- application
|
+-- /data -> persistent volume
|
+-- local.dbAn ephemeral serverless filesystem is different. A function instance may disappear, another instance may start with a different filesystem, and several instances may not share one local file. A successful write to one instance therefore cannot be treated as durable shared state.
This is not a SvelteKit defect or a database-driver defect. It is a mismatch between an embedded database’s storage model and the hosting platform’s filesystem model.
Multiple instances mean multiple local databases
Suppose the service is scaled to three independent instances:
load balancer
| | |
v v v
app app app
| | |
db1 db2 db3Those are three databases, not one database. A row inserted through the first instance does not automatically appear in the other two.
Embedded storage fits well when the application deliberately has one durable node, one database per node, or another design where local ownership is intentional. If every instance must observe the same authoritative dataset, use shared storage or a remote database architecture rather than assuming independent local files will converge.
Sync is a separate architectural choice
Turso also provides @tursodatabase/sync. It keeps a local database while adding synchronization with a remote Turso database:
import { connect } from '@tursodatabase/sync';
const db = await connect({
path: 'local.db',
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!
});Reads and writes can remain local, while push() and pull() exchange mutations with the remote database.
That model is useful when local execution is required but data must also move between machines. It should not be added merely because the application uses embedded storage; synchronization introduces connectivity, conflict, and operational concerns of its own.
For a SvelteKit service that needs one durable local database, @tursodatabase/database keeps the architecture smaller. The decisive production question is not whether connect(’local.db’) works. It is whether the host guarantees that the same database file will still exist, and still be the correct database file, when the next request arrives.