DBOS Transact supports multiple database backends for both system state management and application data. This guide covers how to configure and use PostgreSQL, SQLite, and CockroachDB.
Supported Databases
DBOS supports two database types:
PostgreSQL - Recommended for production. Includes Amazon RDS, Azure Database for PostgreSQL, Google Cloud SQL, and CockroachDB
SQLite - Ideal for development and testing
DBOS uses two databases:
System Database - Stores workflow state, recovery information, and internal metadata
Application Database - Optional database for your application’s @DBOS.transaction() functions
These can be the same database or separate databases. Both must use the same database type (both PostgreSQL or both SQLite).
Quick Start
Choose Your Configuration
PostgreSQL (Production)
SQLite (Development)
PostgreSQL System + Application DB
from dbos import DBOS , DBOSConfig
config = DBOSConfig(
name = "my-app" ,
system_database_url = "postgresql://user:password@localhost/myapp_dbos" ,
application_database_url = "postgresql://user:password@localhost/myapp"
)
DBOS( config = config)
Use Transactions
import sqlalchemy as sa
@DBOS.transaction ()
def create_user ( username : str , email : str ) -> int :
result = DBOS .sql_session.execute(
sa.text(
"INSERT INTO users (username, email) "
"VALUES (:username, :email) RETURNING id"
),
{ "username" : username, "email" : email}
).fetchone()
return result[ 0 ]
PostgreSQL
postgresql://[user]:[password]@[host]:[port]/[database]?[parameters]
Components:
user - Database username (required)
password - Database password (required)
host - Database host (required)
port - Database port (optional, defaults to 5432)
database - Database name (required)
parameters - Additional connection parameters (optional)
Examples
Local PostgreSQL
With Port
With SSL
Connection Timeout
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://postgres:password@localhost/myapp"
)
System Database Configuration
DBOS automatically creates a system database when you provide an application database URL:
config = DBOSConfig(
name = "my-app" ,
# Application database
application_database_url = "postgresql://user:pass@localhost/myapp" ,
# System database automatically created as: myapp_dbos
)
Or specify both explicitly:
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://user:pass@localhost/myapp" ,
system_database_url = "postgresql://user:pass@localhost/myapp_system"
)
Advanced PostgreSQL Configuration
Connection Pooling
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://user:pass@localhost/myapp" ,
db_engine_kwargs = {
"pool_size" : 20 , # Connection pool size
"max_overflow" : 0 , # Additional connections when pool is full
"pool_timeout" : 30 , # Timeout waiting for connection
"pool_pre_ping" : True , # Verify connections before using
},
sys_db_pool_size = 10 # System database pool size
)
Custom Engine Parameters
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://user:pass@localhost/myapp" ,
db_engine_kwargs = {
"connect_args" : {
"application_name" : "my-custom-app" ,
"connect_timeout" : 10 ,
"options" : "-c statement_timeout=30000" # 30 second query timeout
},
"echo" : True , # Log all SQL statements (for debugging)
"pool_pre_ping" : True ,
}
)
SQLite
sqlite:///[path/to/database.sqlite]
Examples
Default (Auto-generated)
Custom Path
Absolute Path
In-Memory (Testing)
# Uses sqlite:///my_app.sqlite
config = DBOSConfig( name = "my-app" )
SQLite Features
Advantages:
Zero configuration for local development
No separate database server required
File-based, portable database
Perfect for testing and prototyping
Limitations:
Not suitable for production deployments
No concurrent writes from multiple processes
Limited scalability
SQLite is recommended for development and testing only. Use PostgreSQL for production deployments.
CockroachDB
CockroachDB is fully compatible with DBOS as it implements the PostgreSQL wire protocol.
Connection String
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://user:password@cockroachdb-host:26257/myapp?sslmode=verify-full"
)
CockroachDB Cloud
config = DBOSConfig(
name = "my-app" ,
application_database_url = (
"postgresql://user:[email protected] :26257/myapp"
"?sslmode=verify-full&sslrootcert=/path/to/ca.crt"
)
)
Features
Distributed, resilient database
PostgreSQL compatibility
Horizontal scalability
Strong consistency guarantees
Built-in replication
Database Configuration Reference
DBOSConfig Parameters
Application name. Must be 3-30 characters, lowercase letters, numbers, dashes, and underscores only.
Connection string for DBOS system database. If not provided, defaults to:
SQLite: sqlite:///{name}.sqlite
PostgreSQL: {application_database_url}_dbos (if application DB is PostgreSQL)
Connection string for application database used in @DBOS.transaction() functions. Optional. If not provided, no application database is configured.
SQLAlchemy engine parameters for application database. See SQLAlchemy documentation . Default values: {
"connect_args" : { "application_name" : "dbos_transact" },
"pool_timeout" : 30 ,
"max_overflow" : 0 ,
"pool_size" : 20 ,
"pool_pre_ping" : True ,
}
Connection pool size specifically for system database. Overrides pool_size from db_engine_kwargs for system DB.
Environment Variables
You can use environment variables in connection strings:
import os
config = DBOSConfig(
name = "my-app" ,
application_database_url = os.environ.get(
"DATABASE_URL" ,
"postgresql://localhost/myapp"
)
)
Or in YAML configuration:
name : my-app
application_database_url : ${DATABASE_URL}
system_database_url : ${SYSTEM_DATABASE_URL}
Using the Application Database
Accessing the SQL Session
In @DBOS.transaction() functions, access the database via DBOS.sql_session:
import sqlalchemy as sa
@DBOS.transaction ()
def get_user ( user_id : int ) -> dict :
result = DBOS .sql_session.execute(
sa.text( "SELECT * FROM users WHERE id = :id" ),
{ "id" : user_id}
).fetchone()
if not result:
return None
return {
"id" : result[ 0 ],
"username" : result[ 1 ],
"email" : result[ 2 ]
}
SQLAlchemy ORM Support
DBOS works with SQLAlchemy ORM models:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base ( DeclarativeBase ):
pass
class User ( Base ):
__tablename__ = "users"
id : Mapped[ int ] = mapped_column( primary_key = True )
username: Mapped[ str ]
email: Mapped[ str ]
@DBOS.transaction ()
def create_user_orm ( username : str , email : str ) -> int :
user = User( username = username, email = email)
DBOS .sql_session.add(user)
DBOS .sql_session.flush()
return user.id
@DBOS.transaction ()
def get_user_orm ( user_id : int ) -> User | None :
return DBOS .sql_session.query(User).filter_by( id = user_id).first()
Read-Only Transactions
@DBOS.transaction ( read_only = True )
def get_users_list () -> list[ dict ]:
results = DBOS .sql_session.execute(
sa.text( "SELECT id, username FROM users" )
).fetchall()
return [{ "id" : r[ 0 ], "username" : r[ 1 ]} for r in results]
Migrations
DBOS automatically manages system database schema migrations. For your application database, use standard migration tools:
Alembic (Recommended)
pip install alembic
alembic init migrations
Configure alembic.ini with your database URL:
sqlalchemy.url = postgresql://user:password@localhost/myapp
Create and run migrations:
alembic revision --autogenerate -m "Create users table"
alembic upgrade head
DBOS CLI Migrations
You can also use DBOS’s built-in migration support:
from dbos import run_dbos_database_migrations
# Run migrations on startup
if __name__ == "__main__" :
run_dbos_database_migrations([ "path/to/migrations" ])
DBOS .launch()
Schema Customization
By default, DBOS system tables use the dbos schema in PostgreSQL. You can customize this:
config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://localhost/myapp" ,
dbos_system_schema = "custom_schema" # Use 'custom_schema' instead of 'dbos'
)
The dbos_system_schema setting cannot be changed after the system database is created. This requires a fresh database or manual migration.
Production Best Practices
Use PostgreSQL for Production
SQLite is not suitable for production. Use PostgreSQL, Amazon RDS, Azure Database for PostgreSQL, or CockroachDB.
Configure Connection Pooling
Set appropriate pool sizes based on your workload: config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://..." ,
db_engine_kwargs = { "pool_size" : 20 , "max_overflow" : 10 },
sys_db_pool_size = 10
)
Enable Connection Health Checks
Use pool_pre_ping=True to verify connections before use: db_engine_kwargs = { "pool_pre_ping" : True }
Set Timeouts
Configure connect and statement timeouts: db_engine_kwargs = {
"connect_args" : {
"connect_timeout" : 10 ,
"options" : "-c statement_timeout=30000"
}
}
Use SSL/TLS
Enable SSL for database connections: application_database_url = "postgresql://user:pass@host/db?sslmode=require"
Separate System and Application Databases
For better isolation and performance: config = DBOSConfig(
name = "my-app" ,
application_database_url = "postgresql://localhost/myapp" ,
system_database_url = "postgresql://localhost/myapp_system"
)
Troubleshooting
Connection Errors
Error: Database name must be specified in the connection URL
Solution: Ensure your PostgreSQL URL includes a database name:
# ❌ Missing database name
"postgresql://user:pass@localhost"
# ✅ Correct
"postgresql://user:pass@localhost/myapp"
Pool Exhaustion
Error: QueuePool limit of size X overflow Y reached
Solution: Increase pool size or reduce concurrent operations:
db_engine_kwargs = { "pool_size" : 30 , "max_overflow" : 20 }
SQLite Concurrency Issues
Error: database is locked
Solution: SQLite doesn’t support concurrent writes. Use PostgreSQL for concurrent workloads.
Next Steps