Performance Optimization
Optimize slow queries and reduce database load in production. Performance Guide
This guide helps you diagnose and fix common issues in FraiseQL applications.
If FraiseQL isn’t working, run through this checklist first:
Check the FraiseQL version
fraiseql --versionValidate configuration
fraiseql validateExpected output when everything is correct:
✓ fraiseql.toml is valid✓ Database connection successful✓ Schema compiles without errors✓ All views exist in databaseTest database connection
fraiseql pingExpected: Database: connected (PostgreSQL 16.1)
Compile schema with verbose output
fraiseql compile --verboseError example:
Error: Syntax error in schema → Line 5: expected ':'Cause: Python syntax error in schema file.
Fix: Check the indicated line for syntax issues:
# Wrong@fraiseql.typeclass User id: str
# Correct@fraiseql.typeclass User: id: strError example:
Error: Type 'Author' not found -> Referenced in Post.author but not definedCause: Referenced type doesn’t exist in schema.
Fix: Define the missing type or fix the reference:
@fraiseql.typeclass User: # Define the type id: str name: str
@fraiseql.typeclass Post: author: User # Now validError example:
Error: Circular reference detected -> User -> Post -> UserCause: Types reference each other in a cycle.
Fix: Use forward references with strings:
@fraiseql.typeclass User: id: str posts: list['Post'] # Forward reference
@fraiseql.typeclass Post: author: 'User' # Forward reference# Error: Missing colon after class definition@fraiseql.typeclass User # ← SyntaxError: expected ':' id: str
# Fix:@fraiseql.typeclass User: id: str
# Error: Wrong annotation syntax@fraiseql.typeclass Post: tags: List[str] # ← NameError: 'List' not defined
# Fix: use built-in list@fraiseql.typeclass Post: tags: list[str]// Error: Missing resolver return type@ObjectType()class User { @Field() id: string; // ← Error: field type must be explicit
// Fix: use explicit Field type decorator @Field(() => String) id: string;}
// Error: Nullable field not declared@ObjectType()class Post { @Field() publishedAt: Date; // ← Error: cannot return null for non-nullable field
// Fix: mark as nullable @Field(() => Date, { nullable: true }) publishedAt?: Date;}Error:
Error: Failed to connect to database -> Connection refused (os error 111)Causes:
Check the server is running:
pg_isready -h localhost -p 5432Test the connection string directly:
psql $DATABASE_URL -c "SELECT 1"Verify the URL format:
postgresql://user:pass@host:port/dbnameError example:
Error: Migration failed -> relation "tb_user" already existsCause: Table already exists from previous migration.
Check migration status to understand what has already been applied:
fraiseql migrate statusIf the state is inconsistent, reset the migration history (CAUTION: drops data in development only):
fraiseql migrate resetAlternatively, remove the conflicting object manually:
psql $DATABASE_URL -c "DROP TABLE IF EXISTS tb_user CASCADE"Error example:
Error: column "pk_user" does not exist -> Referenced in view tv_user definitionCause: View references non-existent column.
Fix: Check table schema matches view definition:
-- Check table columns\d tb_user
-- Ensure column existsALTER TABLE tb_user ADD COLUMN pk_user INTEGER;Error:
Error: function fn_create_user(unknown, unknown) does not existCause: Function signature mismatch.
Inspect the existing function signatures:
\df fn_create_userRecreate the function with explicit parameter types:
CREATE OR REPLACE FUNCTION fn_create_user( user_email TEXT, user_name TEXT) RETURNS UUID AS $$...Error:
{ "errors": [{ "message": "Cannot query field 'username' on type 'User'. Did you mean 'name'?" }]}Cause: Querying non-existent field.
Fix: Use correct field name from schema:
# Wrongquery { users { username } }
# Correctquery { users { name } }Error:
{ "errors": [{ "message": "Variable '$id' expected type 'ID!' but got 'String'" }]}Cause: Variable type doesn’t match schema.
Fix: Use correct type in query:
# Check schema for expected typequery GetUser($id: ID!) { # ID!, not String! user(id: $id) { name }}Error:
{ "errors": [{ "message": "Cannot return null for non-nullable field User.email" }]}Cause: Database returned NULL for required field.
Fix: Either fix data or update schema:
# Option 1: Make field nullableemail: str | None
# Option 2: Ensure data is never nullINSERT INTO tb_user (email, ...) VALUES ('required@email.com', ...)Error:
{ "errors": [{ "message": "Email and name are required" }]}Cause: SQL function validation rejected input.
Fix: Provide required fields:
mutation { createUser( email: "user@example.com", # Required name: "User Name" # Required ) { id }}Error:
{ "errors": [{ "message": "User with email user@example.com already exists" }]}Cause: Duplicate value for unique column.
Fix: Use unique value or update existing:
# Check if exists first, then update or createmutation { updateUser(id: "existing-id", name: "New Name") { id }}Error:
{ "errors": [{ "message": "Author not found" }]}Cause: Referenced entity doesn’t exist.
Fix: Ensure parent entity exists:
# First create usermutation { createUser(email: "...", name: "...") { id } }
# Then create post with valid authormutation { createPost(authorId: "valid-user-id", ...) { id } }Symptom: Queries take > 100ms.
Diagnosis:
-- Enable query loggingALTER SYSTEM SET log_min_duration_statement = 100;SELECT pg_reload_conf();
-- Check slow query logtail -f /var/log/postgresql/postgresql.logCommon fixes:
CREATE INDEX idx_tv_user_email ON tv_user ((data->>'email'));query { users(limit: 20, offset: 0) { id } }# Instead of deeply nestedquery { posts { author { posts { author { ... } } } } }
# Use separate queriesquery { posts { authorId } }query { users(ids: [...]) { name } }Error example:
Error: pool exhausted -> no connections available after 30sCause: Too many concurrent queries.
Fix:
# Increase pool size[database]pool_max = 100 # Increase from default
# Or use external pooling# PgBouncer, pgpool-IISymptom: OOM errors, high memory usage.
Diagnosis:
# Check process memoryps aux | grep fraiseql
# Check PostgreSQL memorySELECT pg_size_pretty(pg_database_size('mydb'));Fixes:
[validation]max_query_depth = 5max_query_complexity = 500[query_defaults]limit = true # ensure limit argument is enabled so clients can paginateError:
{ "errors": [{ "message": "Invalid token" }]}Causes:
Fix:
# Debug tokenecho $TOKEN | cut -d. -f2 | base64 -d | jq
# Check expiry# "exp": 1704067200 (Unix timestamp)
# Verify secret matches# Server uses JWT_SECRET env varError:
{ "errors": [{ "message": "Unauthorized" }]}Cause: Missing or invalid Authorization header.
Fix:
curl -X POST http://localhost:8080/graphql \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"query": "{ users { id } }"}'Error:
{ "errors": [{ "message": "Forbidden: missing scope read:User.email" }]}Cause: Token lacks required scope.
Fix: Request token with required scopes:
# Include scope in tokenjwt.encode({ "sub": user_id, "scope": "read:User.email read:User.name"}, secret)Set the RUST_LOG environment variable before starting FraiseQL:
RUST_LOG=debug fraiseql runAlways check for partial errors:
{ "data": { "users": [...] }, "errors": [ {"message": "Some field failed"} ]}-- Log all queries (development only)ALTER SYSTEM SET log_statement = 'all';SELECT pg_reload_conf();# Test endpointcurl -v http://localhost:8080/graphql
# Check headerscurl -I http://localhost:8080/health
# Test with specific requestcurl -X POST http://localhost:8080/graphql \ -H "Content-Type: application/json" \ -d '{"query": "{ __schema { types { name } } }"}'If you can’t resolve an issue:
fraiseql --version)Performance Optimization
Optimize slow queries and reduce database load in production. Performance Guide
Testing Guide
Write tests to prevent regressions and catch issues early. Testing Guide
Deployment Guide
Production configuration and deployment best practices. Deployment Guide
GitHub Issues
Search for known bugs and report new ones with your diagnostics bundle. Open an Issue
Discord Community
Get real-time help from maintainers and community members. Join Discord
Common Issues
Comprehensive reference organised by error type and symptom. Common Issues