Changelog
v2.1 (Unreleased)
Section titled “v2.1 (Unreleased)”- MySQL
RelayDatabaseAdapter:MySqlAdapternow implementsRelayDatabaseAdapterwith forward and backward keyset pagination.ORDER BYfields useJSON_UNQUOTE(JSON_EXTRACT(data, '$.field')). UUID cursors compare asCHAR(36)strings.totalCountis cursor-independent per the Relay Cursor Connections spec. CheckpointStrategyenum (fraiseql-observers):AtLeastOnce(default, fast, suitable for idempotent consumers) andEffectivelyOnce { idempotency_table }(records an idempotency key before processing; duplicate events detected and skipped viaON CONFLICT DO NOTHING). Methods:is_duplicate(pool, listener_id, key)andrecord_idempotency_key(pool, listener_id, key). Exported from crate root.- k6 load testing baseline and CI workflow:
benchmarks/load/basic.jsramps 10→50 VUs over 50 s (P99 < 500 ms, GraphQL error rate < 1%).benchmarks/load/mutations.jstargets the write path (20 VUs, P99 < 1 000 ms)..github/workflows/perf-baseline.ymlruns on push tomain/devagainst PostgreSQL 16, archives results for 90 days; threshold failures are advisory. - SQL snapshot tests expanded: 21 new
PostgresWhereGeneratorcall-level snapshot tests added totests/sql_snapshots.rscovering all WHERE clause operators, plus 10 MySQL relay snapshots (92 total snapshots).
Changed
Section titled “Changed”fraiseql-clidecoupled fromfraiseql-server:fraiseql-serveris now an optional dependency infraiseql-cli, gated behind arun-serverfeature (enabled by default). TheRuncommand and HTTP stack are conditionally compiled. Building with--no-default-featuresproduces a pure compile-only binary with no server dependency.- TLS consolidated to rustls;
native-tlsremoved: Deadnative-tlsandpostgres-native-tlsdependencies removed fromfraiseql-core. The workspacereqwestdeclaration now usesrustls-tls; all crates (fraiseql-auth,fraiseql-observers,fraiseql-secrets,fraiseql-server) inherit it via{workspace = true}.native-tlsno longer appears in the dependency tree. - Error messages include “Did you mean?” suggestions: Mutation-not-found and fact-table-not-found errors now suggest similarly-named alternatives. OIDC error response body now matches the
WWW-Authenticateheader: expired tokens return"Token has expired", invalid tokens return"Token is invalid".
CachedDatabaseAdapter::cache.put()argument mismatch: Three call sites were passing 4 arguments to a 5-argument signature (missingentity_type), silently breaking cache writes.- Entity-aware cache invalidation:
executor.rsnow callsinvalidate_by_entityfor UPDATE/DELETE mutations whenentity_idis present in the response, enabling precise cache eviction instead of flushing the entire view. View-level flush is still applied for CREATE mutations and wheninvalidates_viewsis explicitly declared.
rc.15 (included in v2.1)
Section titled “rc.15 (included in v2.1)”Release highlights: Multi-transport support. FraiseQL now serves GraphQL, REST, and gRPC from a single compiled schema, on a single port.
Breaking Changes
Section titled “Breaking Changes”[rest]config:prefixrenamed topath. Update your schema TOML:[rest]path = "/rest/v1" # was: prefix = "/rest/v1"
- REST transport: Annotation-driven REST endpoints via
rest_pathandrest_methoddecorator parameters. JSON envelope responses withdata,count,limit,offsetfields. Bracket-syntax filtering (?title=eq.Hello,?age=gt.18). Embedding related resources (?select=*,author(*)). Bulk insert/update/upsert viaPOST/PATCHwith arrays. ETag-based conditional requests (If-None-Match,If-Match).Prefer: return=representation|headers-only|count=exactheader. OpenAPI 3.0.3 spec auto-generated at/rest/v1/openapi.json. - REST direct execution: REST queries bypass the GraphQL resolver layer entirely, executing SQL directly for lower latency. Benchmarked at ~15% fewer allocations than the GraphQL bridge path.
- gRPC transport: Transport-aware database views (
rv_*for REST,va_*for Arrow/gRPC) that skip JSONB serialization. Auto-generated.protodefinitions from the compiled schema. gRPC reflection forgrpcurland Postman discovery. Requiresgrpc-transportCargo feature (not in the default Docker image). - 11 SDK languages: Python, TypeScript, Go, Java, C#, Rust, Elixir, F#, PHP, Ruby, Dart. All produce JSON schema for
fraiseql compile. Python, TypeScript, Go, Java, and C# support REST transport annotations. - Observer system:
[[observers]]TOML syntax for event-driven workflows. LISTEN/NOTIFY on table events (INSERT, UPDATE, DELETE). NATS backend support via[observers]singleton config. Idempotency, retry, and dead-letter patterns. - Admin API:
POST /api/v1/admin/reload-schemafor hot-reload (also viaSIGUSR1). Cache stats, cache clear, config introspection, query explain, and Grafana dashboard export endpoints. Requiresadmin_api_enabled = trueandadmin_tokenin[server]. - Health endpoint:
GET /healthreturns server status includingschema_hashfor deployment verification. - APQ (Automatic Persisted Queries): Enabled by default. Optional Redis backend via
redis-apqfeature +REDIS_URL. Disable withFRAISEQL_APQ_ENABLED=false. - Security features: OIDC/OAuth2 authentication (env-var configured), RBAC with
requires_roledecorator parameter, field-level authorization viarequires_scope, PKCE support, API key authentication, token revocation, trusted documents, rate limiting, state encryption, error sanitization. - Caching: View-level caching with entity-aware invalidation. Cache headers (ETag,
Cache-Control). Configurable TTL per view. - Federation: Multi-database federation with circuit breaker. Cross-database joins via federated views.
- Subscriptions: WebSocket subscriptions via
graphql-wsprotocol.
Changed
Section titled “Changed”- Docker images: Published as
ghcr.io/fraiseql/server:latest(default) andghcr.io/fraiseql/server-full:latest(includes gRPC). Also on Docker Hub asfraiseql/server:latest. - Default port:
8080(bind0.0.0.0). CLI flags override env vars override TOML config.
- Confiture migration tool:
confiture migratefor incremental DDL migrations. Build-from-DDL, production data sync, schema-to-schema comparison. - ELO validation language: Compile-time validation rules for input types, enforced at the Rust runtime layer.
- Trinity Pattern: Convention for table design —
pk_*(internal identity),id(public UUID),identifier(human-readable unique key). Enforced by Confiture scaffolding. - View composition:
v_*views return(id UUID, data JSONB)viajsonb_build_object(). Queries map directly to views with no resolver code. - Custom scalars: Semantic scalar types (Email, Slug, DateTime, URL, PhoneNumber, etc.) validated at the Rust runtime.
- Automatic WHERE clauses: Query arguments whose names match view columns become SQL
WHEREclauses automatically. - Pagination: Offset-based (
limit/offset) and Relay cursor-based (keyset) pagination. - Rich filters: Bracket-syntax operators for equality, comparison, pattern matching, array containment, and range queries.
- CQRS architecture: Separate read path (SQL views) and write path (SQL functions returning
mutation_response). Views are the query layer; functions are the mutation layer. fraiseql compile: Compile SDK schema definitions toschema.json. The compiled artifact is the single source of truth for the Rust runtime.fraiseql run: Start the Rust server from a compiled schema + database connection. Hot-reload viaSIGUSR1.fraiseql init: Scaffold a new project withfraiseql.toml, schema directory, and migration directory.- Python and TypeScript SDKs: Initial schema authoring SDKs. Decorators/annotations produce JSON schema, no runtime FFI.
- PostgreSQL adapter: Connection pooling (
pool_min/pool_max), SSL modes, configurable timeouts.
Previous Releases
Section titled “Previous Releases” GitHub Releases Full release history with tags, assets, and SHA checksums.