LogoLaunchSaaS

Database

LaunchSaaS supports PostgreSQL, MySQL, and SQLite via Drizzle ORM. Connect to Neon, Supabase, PlanetScale, or self-hosted databases with type-safe queries and migrations.

LaunchSaaS uses Drizzle ORM for type-safe database operations. Three database providers are supported out of the box — PostgreSQL, MySQL, and SQLite — each with its own package.

Choosing a Database Provider

ProviderPackageBest for
PostgreSQL (default)@launchsaas/db-pgProduction apps, hosted services (Neon, Supabase, Railway)
MySQL@launchsaas/db-mysqlApps already on MySQL or PlanetScale
SQLite@launchsaas/db-sqlitePrototyping, edge runtimes, local development

The reference app defaults to PostgreSQL. To switch, update these three files in your app:

1. apps/your-app/src/db/index.ts — change the provider export:

export * from "@launchsaas/db-pg"; // PostgreSQL (default)
// export * from "@launchsaas/db-mysql";   // MySQL
// export * from "@launchsaas/db-sqlite";  // SQLite
export * from "./tables";

2. apps/your-app/src/env.ts — change the db keys import:

import { keys as db } from "@launchsaas/db-pg/keys"; // PostgreSQL (default)
// import { keys as db } from "@launchsaas/db-mysql/keys";   // MySQL
// import { keys as db } from "@launchsaas/db-sqlite/keys";  // SQLite

This sets the correct DATABASE_TYPE value that Drizzle Kit reads.

3. apps/your-app/drizzle.config.ts — update the schema path to the matching provider package:

export default defineConfig({
  dialect: env.DATABASE_TYPE,
  schema: ["../../packages/databases/db-pg/src/tables/*", "./src/db/tables/*"], // change db-pg → db-mysql or db-sqlite
  out: "./drizzle",
  dbCredentials: { url: env.DATABASE_URL },
});

After switching providers, regenerate migrations:

pnpm run db:generate
pnpm run db:migrate

Setup

Create a Database

Recommended to use hosted PostgreSQL database services. They provide easy setup and management, and often include free tiers sufficient for getting started.

Neon is a serverless PostgreSQL service with an excellent developer experience.

Setup Steps:

  1. Create an account at neon.tech
  2. Create a new project
  3. Create a database
  4. Get your connection string from the dashboard
  5. Add the connection string to your .env file:
DATABASE_URL="postgres://user:[email protected]/database?sslmode=require"

Supabase

Supabase provides PostgreSQL databases with additional features like authentication and storage.

Setup Steps:

  1. Create an account at supabase.com
  2. Create a new project
  3. Click on the Connect button
  4. Get your connection string in Transaction pooler section
  5. Add the connection string to your .env file:
DATABASE_URL="postgres://postgres:[email protected]:6543/postgres"

Initialize the Database

After configuring your database URL, initialize the database:

pnpm run init

This command will:

  1. Generate database migrations
  2. Apply migrations to your database
  3. Create the admin user

Make sure you have configured DATABASE_URL in your .env file before running this command.

Other Database Options

Self-Hosted

Docker

Run PostgreSQL in a Docker container for local development:

docker run --name launchsaas-postgres -e POSTGRES_PASSWORD=mypassword -d -p 5432:5432 postgres

Connection string:

DATABASE_URL="postgres://postgres:mypassword@localhost:5432/postgres"

Local Installation

Install PostgreSQL directly on your machine from postgres.org.

Other Hosted Services

Database Commands

CommandDescription
pnpm run db:generateGenerate migrations from schema changes
pnpm run db:migrateApply migrations to database
pnpm run db:pushPush schema changes directly (dev only, skips migrations)
pnpm run init:better-authRegenerate Better Auth schema (after auth config changes)
pnpm run init:dbPush the current app schema (used by pnpm run init)

Running Commands for Different Environments

By default, the root commands proxy to apps/launchsaas and load that app's .env file. To run commands against a different environment (for example, staging or production), call drizzle-kit through the app package and point it at a different env file:

# Push schema to the production database
pnpm --filter your-app exec dotenv -e .env.production -- drizzle-kit push --config drizzle.config.ts

# Run migrations on the staging database
pnpm --filter your-app exec dotenv -e .env.staging -- drizzle-kit migrate --config drizzle.config.ts

# Generate migrations using the production database
pnpm --filter your-app exec dotenv -e .env.production -- drizzle-kit generate --config drizzle.config.ts

Be careful when running database commands against production. Always backup your data before running migrations, and prefer db:migrate over db:push in production environments.

Schema Organization

LaunchSaaS now splits DB ownership between the provider package and the app:

  • packages/databases/db-pg/src/tables/ contains the shared PostgreSQL tables used by the template core
  • packages/databases/db-mysql/src/tables/ mirrors the same shared core set for MySQL
  • packages/databases/db-sqlite/src/tables/ mirrors the same shared core set for SQLite
  • apps/launchsaas/src/db/index.ts binds the app to its selected DB provider package
  • apps/launchsaas/drizzle.config.ts owns Drizzle config and migration output
  • apps/launchsaas/src/db/tables/ is reserved for app-specific extra tables

Core shared table definitions are located in packages/databases/db-pg/src/tables/:

FileDescription
auth.tsAuthentication tables (auto-generated by Better Auth)
order.tsOrder table for confirmed monetary transactions
entitlement.tsEntitlement table for user access to products
index.tsRe-exports all schemas

Don't manually edit auth.ts - it's auto-generated. Run pnpm run init:better-auth after changing auth configuration.

Order Table

Represents confirmed monetary transactions:

  • Created when payment is confirmed
  • One-time products create an order upon checkout completion
  • Subscription products create an order upon each successful payment (recurring orders)
  • Contains: provider info, product details, amount, currency, metadata

Entitlement Table

Represents user access to products:

  • Granted/extended when order is paid
  • One-time products create entitlement with status "active" upon checkout
  • Subscription products create entitlement with status "pending", becomes "active" after first payment
  • Contains: subscription period info, cancellation status, provider subscription IDs
  • Supports multiple payment providers (Stripe, Creem, etc.)

FAQ

Connection Issues

If you're having trouble connecting to your database:

  1. Check that your DATABASE_URL is correctly formatted
  2. Ensure your IP is allowed in the database's firewall settings
  3. Verify that the database user has the correct permissions
  4. Check for any network restrictions

Migration Issues

If you're experiencing issues with database migrations:

  1. Check your schema definitions for errors
  2. Ensure your migration scripts are correctly formatted
  3. Try running migrations manually to see detailed errors

References

Next Steps