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
| Provider | Package | Best for |
|---|---|---|
| PostgreSQL (default) | @launchsaas/db-pg | Production apps, hosted services (Neon, Supabase, Railway) |
| MySQL | @launchsaas/db-mysql | Apps already on MySQL or PlanetScale |
| SQLite | @launchsaas/db-sqlite | Prototyping, 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"; // SQLiteThis 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:migrateSetup
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 (Recommended)
Neon is a serverless PostgreSQL service with an excellent developer experience.
Setup Steps:
- Create an account at neon.tech
- Create a new project
- Create a database
- Get your connection string from the dashboard
- Add the connection string to your
.envfile:
DATABASE_URL="postgres://user:[email protected]/database?sslmode=require"Supabase
Supabase provides PostgreSQL databases with additional features like authentication and storage.
Setup Steps:
- Create an account at supabase.com
- Create a new project
- Click on the
Connectbutton - Get your connection string in
Transaction poolersection - Add the connection string to your
.envfile:
DATABASE_URL="postgres://postgres:[email protected]:6543/postgres"Initialize the Database
After configuring your database URL, initialize the database:
pnpm run initThis command will:
- Generate database migrations
- Apply migrations to your database
- 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 postgresConnection 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
| Command | Description |
|---|---|
pnpm run db:generate | Generate migrations from schema changes |
pnpm run db:migrate | Apply migrations to database |
pnpm run db:push | Push schema changes directly (dev only, skips migrations) |
pnpm run init:better-auth | Regenerate Better Auth schema (after auth config changes) |
pnpm run init:db | Push 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.tsBe 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 corepackages/databases/db-mysql/src/tables/mirrors the same shared core set for MySQLpackages/databases/db-sqlite/src/tables/mirrors the same shared core set for SQLiteapps/launchsaas/src/db/index.tsbinds the app to its selected DB provider packageapps/launchsaas/drizzle.config.tsowns Drizzle config and migration outputapps/launchsaas/src/db/tables/is reserved for app-specific extra tables
Core shared table definitions are located in packages/databases/db-pg/src/tables/:
| File | Description |
|---|---|
auth.ts | Authentication tables (auto-generated by Better Auth) |
order.ts | Order table for confirmed monetary transactions |
entitlement.ts | Entitlement table for user access to products |
index.ts | Re-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:
- Check that your
DATABASE_URLis correctly formatted - Ensure your IP is allowed in the database's firewall settings
- Verify that the database user has the correct permissions
- Check for any network restrictions
Migration Issues
If you're experiencing issues with database migrations:
- Check your schema definitions for errors
- Ensure your migration scripts are correctly formatted
- Try running migrations manually to see detailed errors
References
- Neon Documentation
- Supabase Documentation
- Drizzle ORM Documentation
- Drizzle with Neon
- Drizzle with Supabase