Database Setup Guide

Learn how to configure PostgreSQL, MySQL, SQLite, SQL Server, or MongoDB with Stabilize ORM

PostgreSQL Setup
Recommended for production applications

1. Install PostgreSQL

terminal
# macOS
brew install postgresql@18
# Ubuntu/Debian
sudo apt-get install postgresql-18
# Or use a managed service such as Neon, Supabase or AWS RDS

2. Create Database

sql
# Create database
psql postgres -c "CREATE DATABASE myapp;"
# Create user
psql postgres -c "CREATE USER myapp_user WITH PASSWORD 'secure_password';"
psql postgres -c "GRANT ALL PRIVILEGES ON DATABASE myapp TO myapp_user;"

3. Configure Stabilize

config/database.ts
import { Stabilize, DBType, type DBConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.Postgres,
connectionString: "postgresql://myapp_user:secure_password@localhost:5432/myapp",
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};
// Second argument is the cache config; the third would be the logger.
export const orm = new Stabilize(dbConfig, { enabled: false, ttl: 60 });

The connection string is parsed by the driver, which means driver options belong in it — append ?connection_limit=20 to size the pool, since DBConfig has no pool-size field of its own.

MySQL Setup
Popular choice for web applications

1. Install MySQL

terminal
# macOS
brew install mysql
# Ubuntu/Debian
sudo apt-get install mysql-server
# Or use a managed service such as PlanetScale or AWS RDS

2. Create Database

sql
mysql -u root -p -e "CREATE DATABASE myapp;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;"

3. Configure Stabilize

config/database.ts
import { Stabilize, DBType, type DBConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.MySQL,
connectionString: "mysql://myapp_user:secure_password@localhost:3306/myapp",
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};
export const orm = new Stabilize(dbConfig, { enabled: false, ttl: 60 });
SQLite Setup
Perfect for development, testing, and small apps

1. No Installation Required

SQLite is embedded. Stabilize uses the SQLite driver that ships with your runtime — bun:sqlite on Bun, node:sqlite on Node.js — so there is no server to install, start or connect to.

2. Configure Stabilize

config/database.ts
import { Stabilize, DBType, type DBConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.SQLite,
connectionString: "./data/app.db",
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};
export const orm = new Stabilize(dbConfig, { enabled: false, ttl: 60 });

Unlike the other two, connectionString here is a file path, not a URL. Use :memory: for an ephemeral database in tests.

3. File Location

The client opens the file with create: true, so the database is created on first connect — you do not need to make the file yourself. The directory it lives in does have to exist. For production, consider:

  • Using an absolute path
  • Ensuring proper file permissions
  • Regular backups
  • Write-ahead logging (WAL) mode for better concurrency
SQL Server Setup
For existing Microsoft SQL Server or Azure SQL infrastructure

1. Install SQL Server

terminal
# Docker (Linux, macOS, Windows)
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=Your_password123" \
-p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest
# Or use a managed service such as Azure SQL Database

2. Create Database

sql
sqlcmd -S localhost -U sa -P 'Your_password123' -Q "CREATE DATABASE myapp;"

3. Configure Stabilize

config/database.ts
import { Stabilize, DBType, type DBConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.MSSQL,
connectionString:
"Server=localhost,1433;Database=myapp;User Id=sa;Password=Your_password123;TrustServerCertificate=true",
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};
export const orm = new Stabilize(dbConfig, { enabled: false, ttl: 60 });

This is an ADO-style connection string, not a URL — mssql:// is not accepted. TrustServerCertificate=true is needed against a container or any server using a self-signed certificate, or the driver rejects the TLS handshake. The pool opens on the first query rather than at construction, since mssql's connect step is asynchronous. See SQL Server for the dialect differences.

MongoDB Setup
For document-oriented workloads

1. Install MongoDB

terminal
# Docker (Linux, macOS, Windows)
# --replSet is what makes this a single-node replica set; transactions need one
docker run -d --name stabilize-mongo -p 27017:27017 \
mongo:7 --replSet rs0 --bind_ip_all
# Initiate the set once, after the container is up
mongosh --quiet --eval 'rs.initiate({_id:"rs0",members:[{_id:0,host:"127.0.0.1:27017"}]})'
# Or use a managed service such as MongoDB Atlas

2. Install the Driver

terminal
❯bun add mongodb

The driver is an optional dependency and is not installed with the ORM. A missing driver throws MONGO_DRIVER_MISSING on the first statement, not when the config is imported.

3. Configure Stabilize

config/database.ts
import { Stabilize, DBType, type DBConfig } from "stabilize-orm";
const dbConfig: DBConfig = {
type: DBType.MongoDB,
connectionString:
"mongodb://127.0.0.1:27017/myapp?directConnection=true&replicaSet=rs0",
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};
export const orm = new Stabilize(dbConfig, { enabled: false, ttl: 60 });

Two options in the connection string matter here. directConnection=true skips topology discovery, which a single-node set needs when the member registers itself under a container-local address, and replicaSet=rs0 names the set to join. Transactions require a replica set or sharded cluster, and every ORM write is wrapped in one, so a standalone mongod answers every read and then fails every write. The separate database field is consulted only when the connection string has no database path of its own.

Environment Variables

Store database credentials securely using environment variables:

.env
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
config/database.ts
const dbConfig: DBConfig = {
type: DBType.Postgres,
connectionString: process.env.DATABASE_URL!,
retryAttempts: 3,
retryDelay: 1000,
maxJitter: 100,
};

The connection string is the whole story

Every SQL pool is built from connectionString alone. There is no max, min, idleTimeout or connectionLimit field on DBConfig — retries are governed by retryAttempts, retryDelay and maxJitter, and everything else is whatever the driver reads out of the connection string. MongoDB also reads database and mongoOptions.