Skip to content

TOML Configuration

FraiseQL uses a single fraiseql.toml file for all configuration. TOML is human-readable, git-friendly, and has no YAML gotchas.

fraiseql.toml
[project]
name = "my-api"
[database]
url = "${DATABASE_URL}"

That’s it. Everything else has sensible defaults.

The following sections are confirmed valid in fraiseql.toml. Unknown sections cause a hard parse error at fraiseql compile.

fraiseql.toml
# ============================================
# Project Metadata
# ============================================
[project]
name = "my-api"
version = "1.0.0"
# ============================================
# Database Configuration
# ============================================
[database]
url = "${DATABASE_URL}"
pool_min = 2 # default: 2
pool_max = 20
connect_timeout_ms = 5000
idle_timeout_ms = 600000
ssl_mode = "prefer" # disable | allow | prefer | require
# ============================================
# Server Configuration
# ============================================
[server]
host = "0.0.0.0" # default: 0.0.0.0
port = 8080 # default: 8080
request_timeout_ms = 30000
keep_alive_secs = 75
[server.cors]
origins = ["https://app.example.com"]
credentials = true
[server.tls]
cert = "/path/to/cert.pem"
key = "/path/to/key.pem"
# ============================================
# Security
# ============================================
[security]
default_policy = "authenticated" # or "public"
[[security.rules]]
name = "owner_only"
rule = "user.id == object.owner_id"
cacheable = true
cache_ttl_seconds = 300
[[security.policies]]
name = "admin_only"
type = "rbac"
roles = ["admin"]
strategy = "any"
[security.error_sanitization]
enabled = true
hide_implementation_details = true
sanitize_database_errors = true
custom_error_message = "An internal error occurred"
[security.rate_limiting]
enabled = true
requests_per_second = 100
burst_size = 200
[security.state_encryption]
enabled = true
algorithm = "chacha20-poly1305"
key_source = "env"
key_env = "STATE_ENCRYPTION_KEY"
[security.pkce]
enabled = true
code_challenge_method = "S256"
state_ttl_secs = 600
[security.enterprise]
audit_logging_enabled = true
audit_log_level = "info"
# ============================================
# Query Defaults
# ============================================
[query_defaults]
# Default limits and pagination settings
# ============================================
# Federation
# ============================================
[federation]
enabled = true
[federation.circuit_breaker]
enabled = true
failure_threshold = 5
timeout_secs = 30

Use ${VAR_NAME} syntax in fraiseql.toml to reference environment variables:

[database]
url = "${DATABASE_URL}"
[server]
port = 8080

Some settings are only configurable via environment variables (no TOML equivalent):

VariableDescription
DATABASE_URLDatabase connection string
JWT_SECRETJWT signing secret (HS256) or public key path (RS256/ES256)
JWT_ALGORITHMHS256 | RS256 | ES256 (default: HS256)
JWT_ISSUERExpected iss claim (optional)
JWT_AUDIENCEExpected aud claim (optional)
RUST_LOGLog level: error | warn | info | debug | trace
OTEL_EXPORTER_OTLP_ENDPOINTOpenTelemetry collector endpoint
OTEL_SERVICE_NAMEService name for traces

Use separate fraiseql.toml files per environment, or use environment variable substitution to vary values:

Terminal window
# Development
DATABASE_URL=postgresql://localhost:5432/myapp_dev fraiseql run
# Production (different .env file or secrets manager)
DATABASE_URL=postgresql://prod-host:5432/myapp fraiseql run

You can also maintain separate config files:

Terminal window
# Use a different config file
fraiseql run --config fraiseql.production.toml

FraiseQL validates your fraiseql.toml when you run fraiseql compile. Unknown sections cause a hard parse error — this is intentional, so configuration mistakes are caught at build time rather than at runtime.

Terminal window
fraiseql compile
# Error: unknown field `[auth]` in fraiseql.toml at line 12
[project]
name = "my-api"
[database]
url = "postgresql://localhost:5432/myapp_dev"
[server]
port = 8080
Terminal window
# Development logging
RUST_LOG=debug fraiseql run
[project]
name = "my-api"
[database]
url = "${DATABASE_URL}"
pool_min = 5
pool_max = 20
ssl_mode = "require"
[server]
host = "0.0.0.0"
port = 8080
[server.cors]
origins = ["https://app.example.com"]
credentials = true
[security.error_sanitization]
enabled = true
[security.rate_limiting]
enabled = true
requests_per_second = 100
burst_size = 200
Terminal window
# Production env vars
JWT_SECRET=your-256-bit-secret
RUST_LOG=info
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
[project]
name = "multi-tenant-api"
[database]
url = "${DATABASE_URL}"
Terminal window
# JWT includes tenant_id claim — extracted in middleware
JWT_SECRET=your-256-bit-secret

See Multi-Tenancy Guide for RLS and schema-per-tenant patterns.