Skip to content

Multi-Database Support

FraiseQL supports multiple database backends, allowing you to use your preferred database while maintaining the same GraphQL API.

DatabaseStatusBest For
PostgreSQLPrimaryProduction, full feature set
MySQL/MariaDBSupportedMySQL-based infrastructure
SQLiteSupportedDevelopment, embedded, testing
SQL ServerSupportedEnterprise Windows environments
[database]
type = "postgresql"
url = "postgresql://user:password@localhost:5432/mydb"
[database.pool]
min_connections = 5
max_connections = 20
idle_timeout_seconds = 300
[database]
type = "mysql"
url = "mysql://user:password@localhost:3306/mydb"
[database.pool]
min_connections = 5
max_connections = 20
[database.mysql]
# Character set
charset = "utf8mb4"
# Timezone handling
timezone = "UTC"
[database]
type = "sqlite"
url = "sqlite:///path/to/database.db"
# Or in-memory for testing
# url = "sqlite::memory:"
[database.sqlite]
# Journal mode
journal_mode = "wal"
# Busy timeout
busy_timeout_ms = 5000
# Foreign keys
foreign_keys = true
[database]
type = "sqlserver"
url = "mssql://user:password@localhost:1433/mydb"
[database.sqlserver]
# Trust server certificate (dev only)
trust_server_certificate = false
# Application name
application_name = "fraiseql"
# Encrypt connection
encrypt = true
FeaturePostgreSQLMySQLSQLiteSQL Server
JSONB columnsNativeJSON typeJSON1 extNVARCHAR
UUID typeNativeCHAR(36)TEXTUNIQUEIDENTIFIER
ArraysNativeJSONJSONJSON
Full-text searchNativeFULLTEXTFTS5Full-text
Window functionsFullFullLimitedFull
CTEsRecursiveRecursiveRecursiveRecursive
SubscriptionsLISTEN/NOTIFYPollingPollingPolling
Connection poolingDeadpoolDeadpoolSingleDeadpool

Full feature support, recommended for production:

-- Native JSONB with indexing
CREATE TABLE tb_user (
pk_user BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
id UUID DEFAULT gen_random_uuid() UNIQUE,
data JSONB NOT NULL
);
-- GIN index for JSONB
CREATE INDEX idx_user_data ON tb_user USING GIN (data);
-- Native array support
CREATE TABLE tb_post (
tags TEXT[] NOT NULL
);

Advantages:

  • Native JSONB type with full indexing support
  • GIN indexes for efficient JSON queries
  • Native array types
  • LISTEN/NOTIFY for subscriptions

FraiseQL automatically adapts SQL generation per database:

query {
users(where: { email: { _eq: "user@example.com" } }) {
id
name
}
}
SELECT * FROM v_user WHERE data->>'email' = 'user@example.com'
Terminal window
# Export for PostgreSQL
fraiseql-cli generate-views --database postgresql -o postgres.sql
# Export for MySQL
fraiseql-cli generate-views --database mysql -o mysql.sql
Terminal window
# Export data as JSON
fraiseql-cli export --format jsonl > data.jsonl
# Import to new database
fraiseql-cli import --format jsonl < data.jsonl
dev.toml
[database]
type = "sqlite"
url = "sqlite:///dev.db"
Terminal window
# Quick iteration
fraiseql run --config dev.toml
test.toml
[database]
type = "sqlite"
url = "sqlite::memory:"
prod.toml
[database]
type = "postgresql"
url = "${DATABASE_URL}"
[database.pool]
min_connections = 10
max_connections = 50

Uses Deadpool for async connection pooling:

[database.pool]
min_connections = 5
max_connections = 20
connection_timeout_seconds = 30
idle_timeout_seconds = 600
max_lifetime_seconds = 1800

Single connection with WAL mode:

[database.sqlite]
journal_mode = "wal"
busy_timeout_ms = 5000
cache_size = -64000 # 64MB
[database.postgresql]
# Statement timeout
statement_timeout_ms = 30000
# Prepared statements
prepare_threshold = 5
# Extra connection params
options = "-c work_mem=256MB"
[database.mysql]
# Connection params
charset = "utf8mb4"
collation = "utf8mb4_unicode_ci"
# Performance
max_allowed_packet = "64M"
[database.sqlite]
journal_mode = "wal"
synchronous = "normal"
cache_size = -64000
mmap_size = 268435456 # 256MB
Terminal window
# Test connection
fraiseql-cli test-connection --database "${DATABASE_URL}"
  1. Check connection pool settings
  2. Verify indexes on JSON fields
  3. Review query plans with fraiseql-cli explain
Terminal window
# Check database capabilities
fraiseql-cli check-features --database "${DATABASE_URL}"