teta.so

SvelteKit Database Guide: Supabase, Prisma, and More

Explore the best database options for SvelteKit including Supabase, Prisma, Drizzle ORM, MongoDB, and SQLite with setup guides and examples.

Every non-trivial web application needs a database, and SvelteKit gives you complete freedom in choosing one. Because SvelteKit runs server-side code through load functions, form actions, and API endpoints, you can connect to any database that has a JavaScript or TypeScript client. The challenge is not whether you can connect — it is choosing the right database and ORM for your project. This guide covers the most popular database options for SvelteKit projects in 2026, with practical setup examples and honest assessments of when to use each one. If you want a pre-configured database setup, Teta provisions a Supabase PostgreSQL database automatically with every new project.

Database Options for SvelteKit

SvelteKit is database-agnostic. It does not bundle or prefer any specific database. Your server-side code (+page.server.ts, +server.ts, hooks.server.ts) runs in a Node.js environment, so any database client that works with Node.js works with SvelteKit.

The main decision points are:

  • SQL vs NoSQL. Do you need relational data with joins and transactions, or flexible document storage?
  • Managed vs self-hosted. Do you want someone else to handle backups, scaling, and maintenance?
  • ORM vs query builder vs raw SQL. How much abstraction do you want between your code and the database?
  • Edge compatibility. If you deploy to Cloudflare Workers or other edge runtimes, your database client needs to work outside Node.js.

Let's look at the most popular options.

Supabase (PostgreSQL)

Supabase is the most popular database choice for SvelteKit projects, and for good reason. It provides a hosted PostgreSQL database with a REST API, real-time subscriptions, authentication, file storage, and edge functions — all from a single service.

Setup

npm install @supabase/supabase-js @supabase/ssr
// src/hooks.server.ts
import { createServerClient } from '@supabase/ssr';
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
  event.locals.supabase = createServerClient(
    PUBLIC_SUPABASE_URL,
    PUBLIC_SUPABASE_ANON_KEY,
    {
      cookies: {
        getAll: () => event.cookies.getAll(),
        setAll: (cookiesToSet) => {
          cookiesToSet.forEach(({ name, value, options }) => {
            event.cookies.set(name, value, { ...options, path: '/' });
          });
        }
      }
    }
  );
  return resolve(event);
};

Querying Data

// src/routes/posts/+page.server.ts
export async function load({ locals: { supabase } }) {
  const { data: posts, error } = await supabase
    .from('posts')
    .select('id, title, excerpt, published_at, author:profiles(name)')
    .eq('published', true)
    .order('published_at', { ascending: false })
    .limit(20);

  return { posts: posts ?? [] };
}

When to Use Supabase

  • You want a managed PostgreSQL database with zero operational overhead
  • You need authentication, file storage, or real-time features alongside your database
  • You want Row Level Security so the client can query the database directly (safely)
  • You are building a SaaS, marketplace, or app with user-generated content
  • You value having a single platform for backend services

Limitations

  • The JavaScript client uses PostgREST (HTTP), not a direct PostgreSQL connection. Complex queries with multiple joins or subqueries can be awkward to express.
  • Supabase's real-time has a connection limit on the free tier (200 concurrent connections).
  • The free tier limits database size to 500 MB.

Prisma ORM

Prisma is the most widely used ORM in the JavaScript/TypeScript ecosystem. It provides a type-safe database client generated from a schema file, supporting PostgreSQL, MySQL, SQLite, MongoDB, and SQL Server.

Setup

npm install prisma @prisma/client
npx prisma init

Define your schema in prisma/schema.prisma:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Post {
  id          String   @id @default(cuid())
  title       String
  content     String
  published   Boolean  @default(false)
  author      User     @relation(fields: [authorId], references: [id])
  authorId    String
  createdAt   DateTime @default(now())
}

model User {
  id    String @id @default(cuid())
  email String @unique
  name  String
  posts Post[]
}

Generate the client and use it in SvelteKit:

// src/lib/server/database.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();
export default prisma;
// src/routes/posts/+page.server.ts
import prisma from '$lib/server/database';

export async function load() {
  const posts = await prisma.post.findMany({
    where: { published: true },
    include: { author: { select: { name: true } } },
    orderBy: { createdAt: 'desc' },
    take: 20
  });

  return { posts };
}

When to Use Prisma

  • You want full type safety for database queries with auto-completion
  • You prefer defining your schema in code and using migrations
  • Your project has complex relational data with many associations
  • You are connecting to an existing database and need introspection

Limitations

  • Prisma's generated client adds bundle size (can be 5-10 MB in node_modules)
  • Does not work on Cloudflare Workers or other edge runtimes without Prisma Accelerate (a paid proxy)
  • Complex raw SQL queries require escaping Prisma's abstraction layer
  • Cold start time for serverless deployments can be higher due to client initialization

Drizzle ORM

Drizzle is a newer ORM that has gained significant popularity in 2025-2026. It is lighter than Prisma, closer to SQL, and works on edge runtimes.

Setup

npm install drizzle-orm postgres
npm install -D drizzle-kit

Define your schema in TypeScript:

// src/lib/server/schema.ts
import { pgTable, text, boolean, timestamp } from 'drizzle-orm/pg-core';

export const posts = pgTable('posts', {
  id: text('id').primaryKey(),
  title: text('title').notNull(),
  content: text('content').notNull(),
  published: boolean('published').default(false),
  authorId: text('author_id').notNull(),
  createdAt: timestamp('created_at').defaultNow()
});

export const users = pgTable('users', {
  id: text('id').primaryKey(),
  email: text('email').unique().notNull(),
  name: text('name').notNull()
});
// src/lib/server/database.ts
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';

const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client, { schema });
// src/routes/posts/+page.server.ts
import { db } from '$lib/server/database';
import { posts, users } from '$lib/server/schema';
import { eq, desc } from 'drizzle-orm';

export async function load() {
  const results = await db
    .select({
      id: posts.id,
      title: posts.title,
      authorName: users.name
    })
    .from(posts)
    .leftJoin(users, eq(posts.authorId, users.id))
    .where(eq(posts.published, true))
    .orderBy(desc(posts.createdAt))
    .limit(20);

  return { posts: results };
}

When to Use Drizzle

  • You want a lightweight, SQL-like ORM with full TypeScript types
  • You are deploying to edge runtimes (Cloudflare Workers, Deno Deploy)
  • You prefer writing queries that look like SQL rather than object-oriented abstractions
  • You want faster cold starts than Prisma in serverless environments

Limitations

  • Smaller ecosystem and community than Prisma
  • Documentation, while improving, is less comprehensive
  • Fewer adapters for niche databases

MongoDB

MongoDB is the most popular NoSQL database. It stores data as flexible JSON-like documents rather than rows and columns. While less common in the SvelteKit community than PostgreSQL, it has valid use cases.

Setup

npm install mongodb
// src/lib/server/database.ts
import { MongoClient } from 'mongodb';

const client = new MongoClient(process.env.MONGODB_URL!);
const db = client.db('myapp');

export default db;
// src/routes/posts/+page.server.ts
import db from '$lib/server/database';

export async function load() {
  const posts = await db
    .collection('posts')
    .find({ published: true })
    .sort({ createdAt: -1 })
    .limit(20)
    .toArray();

  return { posts };
}

When to Use MongoDB

  • Your data is naturally document-shaped (content management, product catalogs, user-generated content with varying structures)
  • You need flexible schemas that can evolve without migrations
  • You are working with MongoDB Atlas (the managed service) and want global distribution

Limitations

  • No joins in the traditional sense (use $lookup for aggregation, but it is less efficient than SQL joins)
  • ACID transactions are supported but more limited than PostgreSQL
  • Type safety requires additional tooling (Mongoose or manual type definitions)

SQLite

SQLite is an embedded database that stores everything in a single file. It is the most widely deployed database in the world (it is in every smartphone) and works surprisingly well for web applications.

Setup with better-sqlite3

npm install better-sqlite3
npm install -D @types/better-sqlite3
// src/lib/server/database.ts
import Database from 'better-sqlite3';

const db = new Database('data.db');

// Enable WAL mode for better concurrent read performance
db.pragma('journal_mode = WAL');

export default db;
// src/routes/posts/+page.server.ts
import db from '$lib/server/database';

export async function load() {
  const posts = db
    .prepare('SELECT id, title, excerpt FROM posts WHERE published = 1 ORDER BY created_at DESC LIMIT 20')
    .all();

  return { posts };
}

When to Use SQLite

  • Small to medium projects where you want simplicity
  • Prototyping and development (no external database to manage)
  • Read-heavy workloads with moderate write traffic
  • Self-hosted apps on a single server (Fly.io with LiteFS for distributed SQLite)

Limitations

  • Single-writer limitation (only one write at a time)
  • Does not work on serverless or edge platforms (needs file system access)
  • Not suitable for high-write-throughput applications

Choosing the Right Database

Need Best Choice
Full-stack with auth, real-time, storage Supabase
Complex relational data with type safety Prisma + PostgreSQL
Edge deployment with SQL Drizzle + Neon/Turso
Flexible document data MongoDB Atlas
Simple, no external dependencies SQLite
Maximum control, raw SQL Direct pg or postgres client

For most new SvelteKit projects, Supabase is the strongest default choice. It gives you a PostgreSQL database, authentication, real-time subscriptions, and file storage from a single service, with a generous free tier. If you need more control over your queries, pair Supabase's PostgreSQL database with Drizzle or Prisma for the best of both worlds.

Server-Side Data Access Patterns

Regardless of which database you choose, SvelteKit provides consistent patterns for accessing data on the server.

Load functions (+page.server.ts) fetch data before the page renders. This is the primary pattern for reading data.

Form actions handle mutations (create, update, delete) with progressive enhancement. Forms work without JavaScript and enhance automatically when JS is available.

API routes (+server.ts) provide REST endpoints for client-side fetches, webhooks, or external integrations.

Hooks (hooks.server.ts) set up database connections and middleware that run on every request.

The key rule: never import database clients in client-side code. Files under $lib/server/ are excluded from client bundles by SvelteKit, so placing your database modules there ensures credentials and connections never leak to the browser. Teta generates this structure automatically when setting up Supabase integration.

FAQ

What database should I use with SvelteKit?

For most projects, Supabase (PostgreSQL) is the best default. It provides a managed database, authentication, real-time subscriptions, and file storage in one service. If you need a more traditional ORM experience, use Prisma or Drizzle with any PostgreSQL provider. For edge deployments, Drizzle with Neon or Turso offers the best compatibility.

Can I use MongoDB with SvelteKit?

Yes, MongoDB works with SvelteKit. Install the official mongodb package and create a client in a $lib/server/ module. Use it in server load functions and form actions. MongoDB is a good choice when your data is naturally document-shaped, but for most web applications with relational data, PostgreSQL is a better fit.

How do I connect to a database in SvelteKit?

Create a database client in a $lib/server/ module (to ensure it never reaches the browser), then import it in your +page.server.ts load functions, form actions, and +server.ts API routes. Set up the connection in hooks.server.ts if you need it available on every request. Use environment variables for connection strings and credentials.

Is Supabase the best database for SvelteKit?

Supabase is the most popular choice and offers the best overall developer experience for SvelteKit projects. Its combination of PostgreSQL, authentication, real-time, and storage eliminates the need to set up multiple services. However, "best" depends on your needs — Prisma offers stronger type-safe queries, Drizzle is lighter for edge deployments, and MongoDB is better for document-oriented data.

Frequently Asked Questions

What database should I use with SvelteKit?

For most projects, Supabase (PostgreSQL) is the best default. It provides a managed database, authentication, real-time subscriptions, and file storage in one service. If you need a more traditional ORM experience, use Prisma or Drizzle with any PostgreSQL provider. For edge deployments, Drizzle with Neon or Turso offers the best compatibility.

Can I use MongoDB with SvelteKit?

Yes, MongoDB works with SvelteKit. Install the official mongodb package and create a client in a $lib/server/ module. Use it in server load functions and form actions. MongoDB is a good choice when your data is naturally document-shaped, but for most web applications with relational data, PostgreSQL is a better fit.

How do I connect to a database in SvelteKit?

Create a database client in a $lib/server/ module (to ensure it never reaches the browser), then import it in your +page.server.ts load functions, form actions, and +server.ts API routes. Set up the connection in hooks.server.ts if you need it available on every request. Use environment variables for connection strings and credentials.

Is Supabase the best database for SvelteKit?

Supabase is the most popular choice and offers the best overall developer experience for SvelteKit projects. Its combination of PostgreSQL, authentication, real-time, and storage eliminates the need to set up multiple services. However, "best" depends on your needs — Prisma offers stronger type-safe queries, Drizzle is lighter for edge deployments, and MongoDB is better for document-oriented data.

Ready to start building?

Create your next web app with AI-powered development tools.

Comece Grátis
← All articles