Skip to content

Changelog

  • MySQL RelayDatabaseAdapter: MySqlAdapter now implements RelayDatabaseAdapter with forward and backward keyset pagination. ORDER BY fields use JSON_UNQUOTE(JSON_EXTRACT(data, '$.field')). UUID cursors compare as CHAR(36) strings. totalCount is cursor-independent per the Relay Cursor Connections spec.
  • CheckpointStrategy enum (fraiseql-observers): AtLeastOnce (default, fast, suitable for idempotent consumers) and EffectivelyOnce { idempotency_table } (records an idempotency key before processing; duplicate events detected and skipped via ON CONFLICT DO NOTHING). Methods: is_duplicate(pool, listener_id, key) and record_idempotency_key(pool, listener_id, key). Exported from crate root.
  • k6 load testing baseline and CI workflow: benchmarks/load/basic.js ramps 10→50 VUs over 50 s (P99 < 500 ms, GraphQL error rate < 1%). benchmarks/load/mutations.js targets the write path (20 VUs, P99 < 1 000 ms). .github/workflows/perf-baseline.yml runs on push to main/dev against PostgreSQL 16, archives results for 90 days; threshold failures are advisory.
  • SQL snapshot tests expanded: 21 new PostgresWhereGenerator call-level snapshot tests added to tests/sql_snapshots.rs covering all WHERE clause operators, plus 10 MySQL relay snapshots (92 total snapshots).
  • fraiseql-cli decoupled from fraiseql-server: fraiseql-server is now an optional dependency in fraiseql-cli, gated behind a run-server feature (enabled by default). The Run command and HTTP stack are conditionally compiled. Building with --no-default-features produces a pure compile-only binary with no server dependency.
  • TLS consolidated to rustls; native-tls removed: Dead native-tls and postgres-native-tls dependencies removed from fraiseql-core. The workspace reqwest declaration now uses rustls-tls; all crates (fraiseql-auth, fraiseql-observers, fraiseql-secrets, fraiseql-server) inherit it via {workspace = true}. native-tls no 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-Authenticate header: 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 (missing entity_type), silently breaking cache writes.
  • Entity-aware cache invalidation: executor.rs now calls invalidate_by_entity for UPDATE/DELETE mutations when entity_id is present in the response, enabling precise cache eviction instead of flushing the entire view. View-level flush is still applied for CREATE mutations and when invalidates_views is explicitly declared.

Release highlights: Multi-transport support. FraiseQL now serves GraphQL, REST, and gRPC from a single compiled schema, on a single port.

  • [rest] config: prefix renamed to path. Update your schema TOML:
    [rest]
    path = "/rest/v1" # was: prefix = "/rest/v1"
  • REST transport: Annotation-driven REST endpoints via rest_path and rest_method decorator parameters. JSON envelope responses with data, count, limit, offset fields. Bracket-syntax filtering (?title=eq.Hello, ?age=gt.18). Embedding related resources (?select=*,author(*)). Bulk insert/update/upsert via POST/PATCH with arrays. ETag-based conditional requests (If-None-Match, If-Match). Prefer: return=representation|headers-only|count=exact header. 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 .proto definitions from the compiled schema. gRPC reflection for grpcurl and Postman discovery. Requires grpc-transport Cargo 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-schema for hot-reload (also via SIGUSR1). Cache stats, cache clear, config introspection, query explain, and Grafana dashboard export endpoints. Requires admin_api_enabled = true and admin_token in [server].
  • Health endpoint: GET /health returns server status including schema_hash for deployment verification.
  • APQ (Automatic Persisted Queries): Enabled by default. Optional Redis backend via redis-apq feature + REDIS_URL. Disable with FRAISEQL_APQ_ENABLED=false.
  • Security features: OIDC/OAuth2 authentication (env-var configured), RBAC with requires_role decorator parameter, field-level authorization via requires_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-ws protocol.
  • Docker images: Published as ghcr.io/fraiseql/server:latest (default) and ghcr.io/fraiseql/server-full:latest (includes gRPC). Also on Docker Hub as fraiseql/server:latest.
  • Default port: 8080 (bind 0.0.0.0). CLI flags override env vars override TOML config.

  • Confiture migration tool: confiture migrate for 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) via jsonb_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 WHERE clauses 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 to schema.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 via SIGUSR1.
  • fraiseql init: Scaffold a new project with fraiseql.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.