Skip to content

Changelog

Release notes for the ReflexDB engine and control plane. Engine and control plane versions are released independently.


Engine release — pagination correctness guards and a new nested-limit default:

  • AFTER now requires a single-column primary key (integer or text). Tables with a composite or missing primary key return 400 instead of silently skipping rows between pages, and aggregate queries reject AFTER (previously the clause was silently ignored).
  • Text primary keys (UUIDs, varchar ids) now fully support keyset pagination and the deterministic ORDER BY tiebreaker.
  • Malformed cursors are rejected with 400 — previously AFTER '12abc' was silently read as 12.
  • Nested default limit: nested to-many selections without an explicit LIMIT now default to 1000 rows, configurable via query.nested_default_limit (0 restores unbounded). Set an explicit nested LIMIT if you rely on larger nested arrays.
  • GET /schema flags primaryKey only on genuinely unique single-column primary keys — composite-key tables no longer mark a wrong column.
  • Reliability: clean-shutdown hardening in CDC modes, uniform 500 error envelopes with no internal details leaked in headers, and /health/detail JSON-escaping fixes.

Engine release — cold starts, reconnects and degraded mode:

  • No cold-start gap: the replication position is captured before the initial data load (on PostgreSQL the stream opens before the load and buffers through it), so changes committed during a deploy’s initial load are replayed instead of lost until the next write.
  • SQL Server resume reconnects are gap-free: the poller resumes from the pre-disconnect LSN using change-table retention.
  • ETags are boot-scoped: a cached GET /query response can no longer earn a false 304 across an instance restart; If-None-Match now also accepts RFC 9110 lists and weak tags.
  • POST /reload on a cap-degraded instance returns 409 cap_degraded instead of risking an out-of-memory kill (the partial memory budget cannot hold two snapshots during a swap) — resize the instance instead.
  • Retry exhaustion truly halts sync under cdc_reconnect_policy: shutdown: the worker stops polling after the fatal error instead of looping, and the pending change batch is never discarded uncovered.
  • PostgreSQL: the position file is ignored (temporary slots cannot replay a saved LSN) and the engine says so at startup instead of logging a “saved LSN” it cannot honor.

Instances can now be deployed to eu-west-1 (Ireland) or us-east-1 (Virginia). Choose a region per instance at creation time, or set a default on the connection.

  • Region is selected in the Add Instance form
  • The control plane routes all build and deployment operations to the correct region automatically
  • Multi-region is available on Team plan and above

ReflexDB can now connect to MySQL databases that are not publicly accessible, via an SSH bastion host.

  • Configure SSH credentials (host, port, user, private key) per connection
  • The key is stored encrypted at rest — never exposed in logs or API responses
  • A Test Connection preflight runs before any provision or rebuild to catch connectivity issues early
  • Supports RSA, Ed25519, and ECDSA keys in OpenSSH format

See the SSH tunnel setup guide for configuration instructions.


Team plan accounts can now add multiple members:

  • Invite team members by email from Settings → Team
  • Invitees receive an email and can accept with their existing account or a new one
  • Seat limits are enforced per plan
  • Any team member can create connections, databases, and instances; billing stays with the account owner

Two-factor authentication is now available for all accounts:

  • Enable in Account settings → Two-factor authentication
  • Scan the QR code with any TOTP app (Google Authenticator, Authy, 1Password, etc.)
  • MFA is optional; enforcement per team is planned for Business and Enterprise plans

Connections — decoupled source databases

Section titled “Connections — decoupled source databases”

The data model now separates connections (MySQL server credentials) from databases (schema configs and instances):

  • One connection can serve multiple databases with independent schema configs
  • Connection credentials are edited in one place and apply to all associated databases
  • Changing connection credentials offers an option to reconfigure all running instances immediately

Each build now records:

  • Duration — wall-clock seconds from queue to completion
  • Compute tier — build instance size selected based on schema complexity
  • Estimated cost — per-build cost in cents, visible in the build history panel

The dashboard now shows a 30-day uptime percentage on each instance card, derived from the monitoring poll history.


Long-lived rmk_... bearer tokens authenticate against the control plane API and support the same operations as the dashboard. Management keys and the control plane API are not yet generally available — coming soon.


Outbound webhooks can be configured from Settings → Webhooks (see the Webhooks reference):

  • Events: build.completed, build.failed, instance.unhealthy, instance.recovered
  • Payloads are HMAC-signed (X-Reflexdb-Signature) — verify with the secret shown at creation
  • Delivery history and retry controls are available per subscription

CDC reliability — formally verified sync fixes

Section titled “CDC reliability — formally verified sync fixes”

The engine’s snapshot-swap, CDC, and reconnect machinery is now covered by TLA+ model-checked specifications, and model checking surfaced several fixes:

  • No lost updates between POST /reload and CDC sync. Manual reloads and background sync now serialise on a writer lock, so neither can silently overwrite the other’s data. A reload issued while a sync flush or safety-net reload is mid-cycle returns 409 reload_busy immediately instead of waiting it out — retry once the write completes.
  • CDC reconnect no longer misses changes. The stream is reopened before the recovery reload, so changes committed during reconnection are always captured (previously a short gap existed until the safety net fired).
  • Failed batch flushes retry instead of being dropped. A transient load error during a CDC batch flush now keeps the pending change set and retries next tick.
  • resume reconnect mode keeps observed changes. Changes seen before a disconnect are flushed after reconnecting instead of being discarded.
  • Fatal shutdowns exit non-zero. A schema-mismatch shutdown now exits with code 1 so orchestrators and monitoring flag it instead of seeing a clean exit.
  • /health readiness, swap_count, and snapshot age are now published atomically with the snapshot pointer — no more transient disagreement between them.
  • Replication pause takes effect at the next sync tick: a reload already in flight when the pause lands completes first. This was always the behaviour; it is now documented in the per-instance OpenAPI spec, which also gained entries for POST /reload and POST /replication/pause|resume.

COUNT(*), COUNT(field), SUM(field), and AVG(field) are now supported.

Non-aggregate fields in the selection act as implicit GROUP BY keys. Aggregates can also be used inside embedded reverse relations (e.g. count of child rows per parent).

See the Aggregations reference.

The where key on both the root config and individual table entries lets you bake SQL predicates into the snapshot at load time:

where: "deleted_at IS NULL"
where_columns: [deleted_at]

See the Row predicates reference.

Tables, columns, and relations can now be renamed in the generated API without changing the MySQL schema:

field_aliases:
name: display_name
author: writer

See the Field aliases reference.

OpenAPI spec — alphabetical model ordering

Section titled “OpenAPI spec — alphabetical model ordering”

Models in the per-instance OpenAPI spec (GET /openapi.json) are now emitted in alphabetical order, making generated client code deterministic across rebuilds.